当我们使用像 select count(*) from TABLE
这样的语句时,函数 count() 会自动知道它正在计算哪个表。是否可以获取表格并在用户定义的函数中使用它。
drop function if exists related_count;
create function related_count(parent int(11)) returns int(11) deterministic
begin
declare count int(11) default 0;
set count=(select count(*) from TABLENAME where id=parent);
return count;
end;
这样我就可以像这样使用它了:
select count(*),related_count(id) from TABLENAME
这样我就可以不考虑表而使用相同的函数,而不是因为有多个表而定义多个函数。
有没有办法在 select count(*) from TABLENAME1 where id=parent
或 select count(*) from TABLENAME2 where id=parent
之间切换取决于一个变量 related_count('TABLE1',id)
最佳答案
上面@RajeevRanjan 的评论提到使用动态 SQL。这不会起作用,但如果它起作用,它看起来像这样:
create function related_count(tablename varchar(64), parent int) returns int reads sql data
begin
declare count int default 0;
set @sql = concat('select count(*) into count from `', tablename, '` where id = ', parent);
prepare stmt from @sql;
execute stmt;
return count;
end
但是,这是不允许的:
ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger
它不起作用的原因是您的存储函数可能会被本身就是动态 SQL 执行的 SQL 语句中的表达式调用。我猜 MySQL 只允许一个“深度”级别的准备/执行。您不能让准备好的查询运行另一个准备好的查询。
为此,您必须像下面这样对每个表名进行硬编码:
create function related_count(tablename varchar(64), parent int) returns int reads sql data
begin
declare count int default null;
if tablename = 'foo' then set count = (select count(*) from foo where id = parent);
elseif tablename = 'bar' then set count = (select count(*) from bar where id = parent);
elseif tablename = 'baz' then set count = (select count(*) from baz where id = parent);
end if;
return count;
end
这还有一个优点,即它不是 SQL 注入(inject)漏洞,而 PREPARE/EXECUTE 解决方案(如果有效的话)则是。
PS:从其他表读取的函数不是确定性的
。
关于MySQL 使用表名作为函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50078801/