MySQL使用表名作为函数

时间:2018-04-28 16:39:57

标签: mysql function user-defined-functions

当我们使用像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的{​​{1}}或select count(*) from TABLENAME2 where id=parent之间切换

1 个答案:

答案 0 :(得分:2)

@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只允许一个级别" deep"准备/执行。您无法使准备好的查询运行另一个准备好的查询。

为此,您必须对每个表名进行硬编码,如下所示:

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