2010-05-02 88 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 '