2009-10-21 244 views
4

將以逗號分隔的ID作爲varchar發送到MySQL存儲過程時,我無法將該字符串用作IN子句的一部分,並帶有正確的結果返回。該字符串被截斷爲小數點,並且只使用第一個值。在存儲過程中爲'in'子句使用MySQL用戶定義的變量

我想我可以通過準備然後執行語句來解決這個問題,但是這仍然只返回匹配的第一個值。

代碼示例可能會使事情更清晰一些。我想下面的轉換成一個存儲過程(與條款動態):

select id, name from cities where id in (1,2,3); 

這是用事先準備好的聲明我的存儲過程:

DROP PROCEDURE IF EXISTS `cities_select_by_ids` $$ 
CREATE PROCEDURE `cities_select_by_ids`(
    in _cityIds varchar(1000) 
) 
BEGIN 
SET @cityIds = _cityIds; 

PREPARE stmt FROM ' 
    select 
     id, 
     name 
    from cities 
    where id in (?); 
'; 

EXECUTE stmt USING @cityIds; 
DEALLOCATE PREPARE stmt; 

END $$ 
DELIMITER ; 

調用存儲過程我只得到一個比賽爲城市「1」:

call cities_select_by_ids_prepare('1, 2, 3'); 

這裏是一個創建和插入腳本的表和數據:

CREATE TABLE cities (
    id int(10) unsigned NOT NULL auto_increment, 
    name varchar(100) NOT NULL, 
    PRIMARY KEY (`id`) 
); 
insert into cities (name) values ('London'), ('Manchester'), ('Bristol'), ('Birmingham'), ('Brighton'); 

回答

2

由於參數化的工作方式,這是不可能的。

你可以得到它最接近的是:

where find_in_set(id, ?) 

但這不會縮放比例不能使用索引。

+0

謝謝,這是我擔心的 - 至少現在我知道了。 – Nick 2009-10-21 17:20:42

4

試試這個。

DROP PROCEDURE IF EXISTS `cities_select_by_ids_2`; 

CREATE PROCEDURE `cities_select_by_ids_2`(
    in cityIDs varchar(1000) 
) 

BEGIN 

#- ix - index into the list of city IDs 
# cid - city ID 
SET @ix := 1; 
SET @cid := substring_index(cityIDs, ',', @ix); 

LOOP_1: 
WHILE (@cid is not null) DO 
    SELECT id, name 
    FROM cities 
     WHERE id in (@cid) ; 

    #-- substring_index returns complete cityIDs string when index is > number of elements 
    IF (length(substring_index(cityIDs, ',', @ix)) >= length(cityIDs)) THEN 
      LEAVE LOOP_1; 
    END IF; 

    SET @ix := @ix + 1; 
    SET @cid = substring_index(substring_index(cityIDs, ',', @ix), ',', -1); 

END WHILE; 
END 

#---- 
call cities_select_by_ids_2('1, 2'); 
3

另一種選擇。

以下查詢僅適用於存儲過程中支持的PREPARED語句。 MySQL 5.0我認爲。這比使用「find_in_set」更好。使用雙引號「」作爲字符串。

/* Check your mysql version */ 

BEGIN 
SET @sql_text:=concat(
    'SELECT 
     id, 
     name 
    FROM db.table 
    WHERE 
     id IN 
     (', 

     /* BEGIN Parameter */ 
     '91,57', 
     /* END Parameter */ 

     ') ORDER BY id ASC'); 

PREPARE stmt from @sql_text; 
EXECUTE stmt ; 
DEALLOCATE PREPARE stmt; 
END 
+0

這很好,但僅供參考,您在ORDER之前錯過了右括號。 – 2012-11-30 01:30:19

相關問題