【问题标题】:Procedure to loop through comma separated string is not working循环逗号分隔字符串的过程不起作用
【发布时间】:2011-12-05 23:34:15
【问题描述】:

在堆栈溢出中给出的答案的帮助下,我已经更正了代码。我想遍历逗号分隔的 Id 字符串,但不能这样做。下面给出的过程只更新第一条记录,而不更新其他记录。需要进行哪些更正,以便我可以遍历逗号分隔的字符串。 这是我的 SP 的代码

BEGIN
  DECLARE strLen    INT DEFAULT 0;
  DECLARE SubStrLen INT DEFAULT 0;

  IF strIDs IS NULL THEN
   SET strIDs = '';
  END IF;

do_this:
LOOP
SET strLen = LENGTH(strIDs);

UPDATE TestTable SET status = 'C' WHERE Id = SUBSTRING_INDEX(strIDs, ',', 1);

SET SubStrLen = LENGTH(SUBSTRING_INDEX(strIDs, ',', 1));
SET strIDs = MID(strIDs, SubStrLen, strLen);

IF strIDs = NULL THEN
  LEAVE do_this;
END IF;
END LOOP do_this;
END

代码在这篇文章的答案中提供。

我尝试使用 find_in_set() 函数,但它仅在我从头开始传递 ID 时才有效,如果我随机传递 ID 则不起作用。 这是我的表格脚本

CREATE TABLE `testtable` (

Id int(11) 默认为空, Status varchar(255) 整理 utf8_unicode_ci 默认为空 ) ENGINE=MyISAM 默认字符集=utf8 COLLATE=utf8_unicode_ci;

-- ----------------------------
-- Records of testtable
-- ----------------------------
INSERT INTO `testtable` VALUES ('1', 'O');
INSERT INTO `testtable` VALUES ('2', 'O');
INSERT INTO `testtable` VALUES ('3', 'O');
INSERT INTO `testtable` VALUES ('4', 'O');
INSERT INTO `testtable` VALUES ('5', 'O');

这是存储过程 开始 UPDATE TestTable SET status = 'C' WHERE Id = FIND_IN_SET(Id, strIDs); 结束

strIds 是 varchar 类型。

现在试试@strIDs='2'

【问题讨论】:

    标签: mysql stored-procedures


    【解决方案1】:

    试试这个(语法错误已修复且没有 CAST 功能)-

    DELIMITER $$
    
    CREATE PROCEDURE procedure1(IN strIDs VARCHAR(255))
    BEGIN
      DECLARE strLen    INT DEFAULT 0;
      DECLARE SubStrLen INT DEFAULT 0;
    
      IF strIDs IS NULL THEN
        SET strIDs = '';
      END IF;
    
    do_this:
      LOOP
        SET strLen = LENGTH(strIDs);
    
        UPDATE TestTable SET status = 'C' WHERE Id = SUBSTRING_INDEX(strIDs, ',', 1);
    
        SET SubStrLen = LENGTH(SUBSTRING_INDEX(strIDs, ',', 1));
        SET strIDs = MID(strIDs, SubStrLen, strLen);
    
        IF strIDs = NULL THEN
          LEAVE do_this;
        END IF;
      END LOOP do_this;
    
    END
    $$
    
    DELIMITER ;
    

    您可以使用Debugger for MySQL 调试您的程序。

    EDIT2:

    我会在没有程序的情况下这样做。尝试使用FIND_IN_SET 函数,例如-

    SET @strIDs = '1,2,3'; -- your id values
    UPDATE TestTable SET status = 'C' WHERE FIND_IN_SET(id, @strIDs);
    

    或者创建一个临时文件。表,用 id 值填充它并在 UPDATE 语句中连接这两个表。

    【讨论】:

    • 它不工作..错误显示在 DECLARE StrLen。我正在为 MySQl 使用 Navicat 8 Lite。无法调试
    • @Devart..如果我删除前导和尾随 DELEMETER,它会起作用,但如果我将 '1,2,3' 作为字符串传递,则不会循环。我想更新 ID 为 1、2、3 的状态,但它只更新 1
    • @Devart..我确实喜欢这个。 BEGIN UPDATE TestTable SET status = 'C' WHERE Id = FIND_IN_SET(id, strIDs);但它没有醒来。它显示了一些语法错误 END
    • @Devart..对不起,但它仅在我从表中的第一个 ID 开始传递 ID 时才有效,如果我随机传递 ID 则不起作用。
    • Procedure 的参数 strIDs 和 @strIDs 是不同的变量。并尝试无程序处理。
    【解决方案2】:

    也许这篇文章有点太旧了,但我已经尝试过 Devart 提供的代码,但它不适合我。

    稍加修改,这个版本对我有用:

    DELIMITER $$
    
    CREATE PROCEDURE procedure1(IN strIDs VARCHAR(255))
    BEGIN
      DECLARE strLen    INT DEFAULT 0;
      DECLARE SubStrLen INT DEFAULT 0;
    
      IF strIDs IS NULL THEN
        SET strIDs = '';
      END IF;
    
    do_this:
      LOOP
        SET strLen = CHAR_LENGTH(strIDs);
    
        UPDATE TestTable SET status = 'C' WHERE Id = SUBSTRING_INDEX(strIDs, ',', 1);
    
        SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(strIDs, ',', 1)) + 2;
        SET strIDs = MID(strIDs, SubStrLen, strLen);
    
        IF strIDs = '' THEN
          LEAVE do_this;
        END IF;
      END LOOP do_this;
    
    END
    $$
    
    DELIMITER ;
    

    解释:

    1) 为什么在SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(strIDs, ',', 1)) + 2; 中“+2”

    当你在下一行执行MID函数时,字符串索引从1开始。如果你有下面的字符串'4500,2',用Devart版本,MID看起来像MID('4500,2',4, 6) 即返回 ',2'。

    因此,如果您在子字符串长度处添加 1,则您位于分隔符上。这不够。 所以你添加分隔符的长度。现在好了。

    2) 为什么IF strIDs = '' THEN 在循环条件中?

    因为当你做 MID 时你会返回一个字符串,即使这个字符串是空的。

    Devart 程序已修补!非常感谢你的回答:)

    【讨论】:

      【解决方案3】:

      我没有找到任何合适的方法,所以我最终自己制作了。这很简单。

      PROCEDURE db.loop_through_array()
      BEGIN
      
        DECLARE strIDs varchar(150) DEFAULT 'one,two,three';
        DECLARE element varchar(150);
      
        WHILE strIDs != '' DO
      
          SET element = SUBSTRING_INDEX(strIDs, ',', 1);      
      
          UPDATE TestTable SET status = 'C' WHERE Id = element;
      
          IF LOCATE(',', strIDs) > 0 THEN
            SET strIDs = SUBSTRING(strIDs, LOCATE(',', strIDs) + 1);
          ELSE
            SET strIDs = '';
          END IF;
      
        END WHILE;
      
      END
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多