在MySQL中:如何将表名作为存储过程和/或函数参数传递?

32
例如,以下内容是无法正常工作的:
DELIMITER //
CREATE PROCEDURE countRows(tbl_name VARCHAR(40))
  BEGIN
    SELECT COUNT(*) as ct FROM tbl_name;
  END //

DELIMITER ;
CALL countRows('my_table_name');

产生:

ERROR 1146 (42S02): Table 'test.tbl_name' doesn't exist

然而,这个操作按预期运作:

SELECT COUNT(*) as ct FROM my_table_name;

在select语句中使用参数作为表名需要什么语法?这是否可能?


1
即使这是可能的,这也不是你应该走下去的路。要么使用你真正想要的 SQL 构建 s'procs,要么直接在代码中嵌入临时 SQL。 - NotMe
8
@Chris,你能看到这里的意图和力量吗?将表名传递给通用函数。我认为这是完全合理和必要的。请帮助我理解为什么从存储过程中控制结果集是不好的?根据你所说的,如果我有一个.NET开发人员和一个PHP开发人员,我应该要求他们编写自己的代码来获取相同的结果集吗? - randomx
我理解你的意图,但它存在缺陷。我强烈建议你阅读以下内容:http://www.sommarskog.se/dynamic_sql.html。虽然它是关于MS SQL Server的,但其中的教训同样适用。 - NotMe
这里还有另一个信息丰富的链接:http://sqlskills.com/BLOGS/KIMBERLY/post/Little-Bobby-Tables-SQL-Injection-and-EXECUTE-AS.aspx - NotMe
2个回答

41

准备语句 是你需要的。

CREATE  PROCEDURE `test1`(IN tab_name VARCHAR(40) )
BEGIN
 SET @t1 =CONCAT('SELECT * FROM ',tab_name );
 PREPARE stmt3 FROM @t1;
 EXECUTE stmt3;
 DEALLOCATE PREPARE stmt3;
END $$

+1:你第一个回答正确 - 你必须使用预处理语句(MySQL的动态SQL):http://rpbouman.blogspot.com/2005/11/mysql-5-prepared-statement-syntax-and.html - OMG Ponies
3
调用 GetNumRows(gps_location) 函数返回:#1054 - 在字段列表中未知列 'gps_location' - grepsedawk
@a1ex07 但是如果我想声明一个游标,并且在一个语句中需要连接和调用过程,该怎么办? - VB_
1
@V_B:我认为你需要提出一个单独的问题,这个问题很旧了,而且我不明白有没有游标与原始问题有什么关系... - a1ex07
@Pachonk gps_location 在这一点上可以作为 SQL 可以使用的东西,是一个列名、变量等。该函数连接字符串,因此您必须传入字符串。 - Daniel
1
MySQL的预处理语句页面链接已失效。请使用以下链接:MySQL 8.0中的预处理语句 - Diggi55

4
你可以像这样做:
 DROP PROCEDURE IF EXISTS `getDataUsingSiteCode`;
    DELIMITER $$
    CREATE PROCEDURE `getDataUsingSiteCode`(
          IN tab_name VARCHAR(40), 
          IN site_ VARCHAR(255)
       )
        BEGIN
          SET @site_code = site_;
          SET @sql_ =CONCAT('SELECT * FROM ',tab_name,' WHERE site=?');
          PREPARE statement_ FROM @sql_;
          EXECUTE statement_ using @site_code;
        END$$
    DELIMITER ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接