【问题标题】:Using MySQL user-defined variable in stored procedure for 'in' clause在“in”子句的存储过程中使用 MySQL 用户定义的变量
【发布时间】:2010-12-08 18:47:22
【问题描述】:

当将逗号分隔的 id 字符串(作为 varchar)发送到 MySQL 存储过程时,我无法将该字符串用作 IN 子句的一部分,并返回正确的结果。字符串被截断为小数,仅使用第一个值。

我认为我可以通过准备然后执行语句来解决这个问题,但这仍然只返回第一个值的匹配项。

代码示例可能会让事情变得更清晰。我想将以下内容转换为存储过程(使用 in 子句动态):

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');

【问题讨论】:

    标签: sql mysql stored-procedures


    【解决方案1】:

    试试这个。

    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');
    

    【讨论】:

      【解决方案2】:

      另一种选择。

      下面的查询仅适用于存储过程中支持的 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
      

      【讨论】:

      • 这很好,但仅供参考,您在 ORDER 之前缺少一个右括号。
      【解决方案3】:

      由于参数化的工作方式,这是不可能的。

      你能得到它的最接近的:

      where find_in_set(id, ?)
      

      但这不会像不能使用索引那样扩展。

      【讨论】:

      • 谢谢,这正是我所担心的——至少我现在知道了。
      猜你喜欢
      • 1970-01-01
      • 2013-07-12
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多