2011-10-12 28 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