循环逗号分隔字符串的过程无效

时间:2011-10-12 09:31:52

标签: mysql stored-procedures

我已经在堆栈溢出给出的答案的帮助下纠正了代码。我想循环逗号分隔的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)DEFAULT NULL,     Status varchar(255)COLLATE utf8_unicode_ci DEFAULT NULL     )ENGINE = MyISAM DEFAULT CHARSET = 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);     END

strIds是varchar类型。

现在尝试@ strIDs ='2'

3 个答案:

答案 0 :(得分:17)

也许这篇文章有点太陈旧但是我尝试了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)为什么“+2”IN SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(strIDs, ',', 1)) + 2;

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

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

2)为什么IF strIDs = '' THEN处于循环状态?

因为当您执行MID时,即使此字符串为空,也会返回一个字符串。

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

答案 1 :(得分:7)

尝试这个(语法错误是固定的,没有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);

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

答案 2 :(得分:5)

我找不到任何合适的方法,所以我自己做了,这非常简单。

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