在MySQL存储过程中使用变量作为表名

44

我试图将表名传递给我的MySQL存储过程,以便使用此存储过程从不同的表中选择数据,但似乎并没有起作用...

这是我尝试的代码:

CREATE PROCEDURE `usp_SelectFromTables`(
 IN TableName varchar(100)
)
BEGIN
        SELECT * FROM @TableName;
END
我也尝试过去掉@符号,但只是告诉我TableName不存在...这个我知道 :)
3个回答

71
SET @cname:='jello';
SET @vname:='dwb';
SET @sql_text = concat('select concept_id,concept_name,',@vname,' from enc2.concept a JOIN enc2.ratings b USING(concept_id) where concept_name like (''%',@cname,'%'') and 3 is not null order by 3 asc');

PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

哇,这是一个非常棒的方法! - user1663023
5
这如何回答问题?OP问如何将表名作为变量传递到存储过程中!!! - Ifedi Okonkwo
@ifedi:没错。所以我想CONCAT函数应该包括使用(IN tableName)语句传递的变量名... - Fabien Haddadi
1
另外,请记住在存储过程中,您不必使用@varname:= 'XXX'@varname来读取它们,而只需将其声明为变量,然后使用SET varname = value,并且 SELECT value 即可... - Fabien Haddadi

19

一个额外的细节让我遇到了问题。

我想在查询中动态设置表名和字段,就像@kyle所问的那样,但我还想在查询中将该查询的结果存储到变量@a中。

您需要将变量@a作为字符串文本的一部分包含,而不是将其直接放入concat中。

delimiter //

CREATE PROCEDURE removeProcessed(table_name VARCHAR(255), keyField VARCHAR(255), maxId INT, num_rows INT)

BEGIN
  SET @table_name = table_name;
  SET @keyField = keyField;
  SET @maxId = maxId;
  SET @num_rows = num_rows;

  SET @sql_text1 = concat('SELECT MIN(',@keyField,') INTO @a FROM ',@table_name);
  PREPARE stmt1 FROM @sql_text1;
  EXECUTE stmt1;
  DEALLOCATE PREPARE stmt1;

  loop_label:  LOOP
    SET @sql_text2 = concat('SELECT ',@keyField,' INTO @z FROM ',@table_name,' WHERE ',@keyField,' >= ',@a,' ORDER BY ',@keyField,' LIMIT ',@num_rows,',1');
    PREPARE stmt2 FROM @sql_text2;
    EXECUTE stmt2;
    DEALLOCATE PREPARE stmt2;

    ...Additional looping code...

    END LOOP;
END
//

delimiter ;

所以在@sql_text1中,使用以下语句将查询结果分配给字符串中的@a:

') INTO @a FROM '

然后在@sql_text2中使用@a作为实际变量:

,' WHERE ',@keyField,' >= ',@a,' ORDER BY '


17

这取决于DBMS,但通常需要使用动态SQL符号,并遇到一个问题:当函数执行时,返回值取决于输入。这使得系统混乱不堪。一般来说(因此可能有例外),DBMS不允许您在查询的结构元素(例如表名或列名)中使用占位符(参数);他们只允许您指定诸如列值之类的值。

一些DBMS确实支持存储过程,这将允许您建立一个SQL字符串,然后使用“prepare”或“execute immediate”等操作进行操作。但请注意,您突然变得容易受到SQL注入攻击的攻击 - 能够执行您的过程的人能够在某种程度上控制要执行的SQL。


(在你的变量名数据类型中)我更喜欢使用IN/OUT,这样我可以提供一个动态变量,而不仅仅是将静态变量硬编码到存储过程中。但在有人建议验证之前,因为您应该始终进行验证,表单端和服务器端都要进行验证,以确保安全,但无论如何。 - easleyfixed

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