2011-10-12 78 views
4

我已经通过堆栈溢出中给出的答案纠正了代码。我想遍历逗号分隔的字符串,但不能这样做。下面给出的过程只更新第一条记录而不更新其他记录。需要进行哪些更正才能通过逗号分隔的字符串进行循环。 这是我的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()函数,但它只有在我通过ids从头开始而不工作的情况下才起作用,如果我随机传递Ids。 这是我的表脚本

CREATE TABLE `testtable` (

Id INT(11)DEFAULT NULL, Status VARCHAR(255)COLLATE utf8_unicode_ci DEFAULT NULL )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'); 

这是存储过程 BEGIN UPDATE SET TestTable的状态= 'C' 其中id = FIND_IN_SET(ID,strIDs); END

strIds是varchar类型。

现在尝试@ strIDs = '2'

回答

6

试试这个(语法错误是固定的,没有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语句中加入这两个表。

+0

它不工作..错误显示在DECLARE StrLen。我正在使用Navicat 8 Lite for MySQl。调试是不可能的 –

+0

@ Devart..Its工作,如果我删除前导和尾DELEMETER,但不循环,如果我通过'1,2,3'作为字符串。我想更新Ids为1,2,3的状态,但它只更新为1 –

+0

我修改了我的答案。 – Devart

15

也许这篇文章有点过时,但我尝试了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程序已修补!非常感谢您的支持:)

4

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

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