mysql对函数使用表名

zfycwa2u  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(576)

当我们使用这样的语句 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)

rbpvctlc

rbpvctlc1#

上面来自@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

但是,这是不允许的:
错误1336(0a000):存储函数或触发器中不允许使用动态sql
它不起作用的原因是,存储的函数可能会被本身是动态sql执行的sql语句中的表达式调用。我猜mysql只允许一个级别的prepare/execute。不能让准备好的查询运行另一个准备好的查询。
为此,必须对每个表名进行硬编码,如下所示:

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注入漏洞,而prepare/execute解决方案(如果它起作用的话)则是。
ps:从其他表读取的函数不是 deterministic .

相关问题