2014-04-11 12 views
0

MySQL 5.0中在MySQL中如何將整數列表傳遞給存儲過程中的預處理語句?

CREATE TABLE `locationcodes` (
    `id` int, 
    `customer` varchar(100), 
    `locationcode` varchar(50), 
    `parentid` int 
); 

insert into locationcodes values (1, 'Test, Inc.', 'California', NULL); 
insert into locationcodes values (2, 'Test, Inc.', 'Los Angeles', 1); 
insert into locationcodes values (3, 'Test, Inc.', 'San Francisco', 1); 
insert into locationcodes values (4, 'Test, Inc.', 'Sacramento', 1); 

存儲過程:

CREATE PROCEDURE test (_location VARCHAR(100)) 
BEGIN 

SET @location = _location; 

SET @select=' 
    SELECT id, locationcode 
    FROM locationcodes 
    WHERE customer="Test, Inc." 
    AND id in (?) 
    '; 

PREPARE stmt FROM @select; 
EXECUTE stmt USING @location; 
DEALLOCATE PREPARE stmt; 

END 

通話過程:

call test('2, 3') 

結果:

2, Los Angeles 

結果是隻有一行,但我WOU ld像兩行。挑戰是準備好的聲明看到參數是一個varchar,並相應地引用了該值。我寧願沒有引號,以便我可以創建一個IN語句,那該怎麼做?理想情況下,MySQL將有一個ints數據類型的列表,所以我不必使用varchar,但不存在。

我需要保留準備好的語句以防止SQL注入攻擊。

回答

1

看起來不可能在IN()中使用預備語句並綁定一個單一值。

由於某些原因,當只有一個值在相應的比較中進行綁定時,MySQL的API會用=(等於)替換IN()。

我用我們的程序運行一些測試,這就是我得到的。

隨着你原來這就是MySQL的生成過程(測試我的默認數據庫):

((`test`.`locationcodes`.`customer` = 'Test, Inc.') and 
(`test`.`locationcodes`.`id` = '2,3')) 

在這種情況下,域ID是整數和MySQL轉換「2,3」 2的對比,這是爲什麼它返回洛杉磯,'3,2'顯然會返回'舊金山'。

只是爲了確保這與字段類型(id是一個整數)沒有關係,我嘗試將該值與位置代碼(varchar)進行比較,結果是相同的。

我改變了你的過程綁定兩個值而不是一個。

... 
SET @select=' 
    SELECT id, locationcode 
    FROM locationcodes 
    WHERE customer="Test, Inc." 
    AND id in (?,?) 
    '; 

PREPARE stmt FROM @select; 
EXECUTE stmt USING @location,@location2; 
... 

在這種情況下,正確地創建聲明。

((`test`.`locationcodes`.`customer` = 'Test, Inc.') and 
(`test`.`locationcodes`.`id` in ('2','3'))) 

話雖這麼說,我可以告訴你將不得不使用另一種方法來實現這一目標用事先準備好的聲明。

經過我的測試,我發現這個bug報告http://bugs.mysql.com/bug.php?id=16564

據瓦列裏,創建具有價值的臨時表和使用JOIN。它應該工作。

相關問題