2011-10-12 20 views
4

J'ai corrigé le code à l'aide de la réponse donnée dans le débordement de la pile. Je veux parcourir la chaîne d'ID séparés par des virgules, mais je ne peux pas le faire. La procédure ci-dessous ne met à jour que le premier enregistrement et ne met pas à jour les autres enregistrements. Quelles corrections sont nécessaires pour que je puisse faire une boucle dans une chaîne séparée par des virgules. Ce est le code de mon SPLa procédure pour faire une boucle entre les chaînes séparées par des virgules ne fonctionne pas

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 

Le code est tel que prévu dans les réponses à ce poste.

J'ai essayé avec la fonction find_in_set() mais cela ne fonctionne que si je passe les identifiants depuis le début et ne fonctionne pas si je passe les Ids aléatoirement. Ceci est mon script pour la table

CREATE TABLE `testtable` (

Id int (11) NULL DEFAULT, Status varchar (255) COLLATE utf8_unicode_ci NULL DEFAULT ) MOTEUR = 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'); 

Ceci est la procédure stockée BEGIN UPDATE TestTable état SET = 'C' où ID = FIND_IN_SET (Id, strIDs); END

strIds est de type varchar.

Maintenant essayez @ strIDs = '2'

Répondre

6

Essayez celui-ci (erreurs de syntaxe sont fixes et sans fonction 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 ; 

Vous pouvez déboguer votre procédure avec Debugger for MySQL.

EDIT2:

Je le ferais sans procédure. Essayez d'utiliser la fonction FIND_IN_SET, par ex. -

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

Ou créer une temp. table, remplissez-le avec les valeurs id et joignez ces deux tables dans l'instruction UPDATE.

+0

Il ne fonctionne pas..L'erreur est montrée àDECLARE StrLen. J'utilise Navicat 8 Lite pour MySQl. Le débogage n'est pas possible –

+0

@ Devart..Elle fonctionne si je supprime DELEMETER avant et arrière, mais ne boucle pas si je passe '1,2,3' sous forme de chaîne. Je veux mettre à jour le statut où les IDs sont 1,2,3 mais il ne met à jour que pour 1 –

+0

J'ai modifié ma réponse. – Devart

15

Peut-être que cet article est un peu trop vieux mais j'ai essayé le code présenté par Devart et ça ne marche pas pour moi.

Avec quelques modifications, cette version fonctionne pour moi:

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 ; 

Explications:

1) Pourquoi "2" EN SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(strIDs, ',', 1)) + 2;

Lorsque vous exécutez la fonction MID sur la ligne suivante , l'index de chaîne commence par 1. Si vous avez la chaîne suivante '4500,2', avec la version Devart, MID ressemble à MID ('4500,2', 4,6) qui est de retour ', 2'. Donc, si vous ajoutez 1 à la longueur de la sous-chaîne, vous êtes sur le délimiteur. Ce n'est pas assez. Vous ajoutez donc la longueur du délimiteur. Maintenant c'est bon.

2) Pourquoi IF strIDs = '' THEN dans la condition de boucle? Parce que lorsque vous faites MID, vous renvoyez une chaîne même si cette chaîne est vide.

La procédure Devart est corrigée! Merci beaucoup pour votre réponse :)

4

J'ai échoué à trouver une méthode appropriée, alors j'ai fait la mienne, ce qui est assez simple.

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 
Questions connexes