2010-05-02 81 views
23

我想要一个表名传递到我的MySQL存储过程来使用这个存储过程不同的表来选择关闭,但它不工作...使用表名称的变量在MySQL存储过程

这是什么我“米试图:

CREATE PROCEDURE `usp_SelectFromTables`(
IN TableName varchar(100) 
) 
BEGIN 
     SELECT * FROM @TableName; 
END 

我也尝试了W/O @符号和刚刚告诉我,表名不存在......我知道:)

回答

12

这取决于DBMS,但是这个表示法通常需要动态SQL,并且会遇到来自f的返回值的问题当它被执行时取决于输入。这给出了系统的配置。作为一个通用规则(因此可能会受到例外),DBMS不允许您为查询的结构元素使用占位符(参数),例如表名或列名;它们只允许您指定值,如列值。

一些DBMS确实具有存储过程支持,它允许您构建一个SQL字符串,然后使用“准备”或“立即执行”或类似操作来处理该字符串。但是,请注意,您突然容易受到SQL注入攻击 - 可以执行您的过程的人可以部分控制SQL执行的部分内容。

44
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; 
+0

哇,什么是bril liant的方式! – 2015-12-14 05:55:00

12

额外的一点,导致我的问题。

我想在查询中动态地设置表名和字段为@kyle询问,但我也想将查询的结果存储到查询中的变量@a

从字面上将变量@a放入concat而不是将其作为字符串文本的一部分包含进去。在@sql_text2使用@a

') INTO @a FROM '

然后作为一个实际的变量::

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字符串内

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