2009-10-21 241 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

相关问题