Процедура перебрать строку через запятую не работает - PullRequest
7 голосов
/ 12 октября 2011

Я исправил код с помощью ответа, указанного в переполнении стека.Я хочу пройти через строку идентификаторов через запятую, но не могу этого сделать.Ниже приведенная процедура только обновляет первую запись, а не обновляет другие записи.Какие исправления необходимы, чтобы я мог пройти через строку через запятую.Это код для моего 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 start.от начала и не работает, если я передаю идентификаторы случайно.Это мой скрипт для таблицы

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;1011 *

-- ----------------------------
-- 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 TestTable SET status = 'C' WHERE Id = FIND_IN_SET (Id, strIDs);END

strIds имеет тип varchar.

Теперь попробуйте @ strIDs = '2'

Ответы [ 3 ]

17 голосов
/ 05 декабря 2012

Возможно, этот пост слишком старый, но я попробовал код, представленный 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процедура залатана!Большое спасибо за ваш ответ:)

7 голосов
/ 12 октября 2011

Попробуйте это (синтаксические ошибки исправлены и без функции 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 ;

Вы можете отладить вашу процедуру с помощью Отладчик для 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.

5 голосов
/ 02 августа 2016

Мне не удалось найти подходящий метод, поэтому я сделал свой собственный, что довольно просто.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...