Как бороться с отсутствующими строками в цикле моей хранимой процедуры? - PullRequest
0 голосов
/ 04 июля 2019

У меня есть эта процедура, которая перебирает значения article, выбирает tag1 и вставляет ее в таблицу article_tag:

DELIMITER $$
CREATE PROCEDURE dt1()
BEGIN
    DECLARE maxid INT;
    DECLARE x INT;
    DECLARE t VARCHAR(30);
    DECLARE ntag1 int;
    SET maxid = (SELECT MAX(id) FROM `article`);
    SET x = (SELECT MIN(id) FROM  `article`) ;
    WHILE x<= maxid DO 
        SET t = (SELECT tag1 from `article` WHERE id=x);   
        SET ntag1 = (SELECT count(*) from `article_tag` WHERE tag=t);

        IF ntag1 = 0 
        THEN 
            INSERT INTO `article_tag` (tag, slug, frequency) VALUES (t, t, 1);
        ELSE 
            UPDATE  `article_tag` SET frequency = frequency + 1 WHERE tag=t;
        END IF;
        SET  x = x + 1; 
    END WHILE;
END$$

Этот отлично работает , когда в цикле while есть строки с id, но когда между ними пропущены id с (например, здесь ) Я получаю

Query Error: Error: ER_BAD_NULL_ERROR: Column 'tag' cannot be null

Мне интересно, как идиоматический способ справиться с такими пропущенными строками?

1 Ответ

2 голосов
/ 05 июля 2019

Вы можете использовать цикл с курсором, поэтому вы будете выполнять цикл только по существующим записям и не нужно проверять NULL.Примерно так:

DELIMITER \\
CREATE PROCEDURE dt1()
BEGIN
    DECLARE t VARCHAR(30);
    DECLARE done INT DEFAULT FALSE;
    DECLARE cur1 CURSOR FOR SELECT tag FROM `article` ORDER BY id;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN cur1;

    loop1: LOOP
        FETCH cur1 INTO t;
        IF done THEN
            LEAVE loop1;
        END IF;

        SELECT COUNT(*) INTO @cnt from `article_tag` WHERE tag = t;

        IF @cnt = 0  THEN 
            INSERT INTO `article_tag` (tag, slug, frequency) VALUES (t, t, 1);
        ELSE 
            UPDATE `article_tag` SET frequency = frequency + 1 WHERE tag = t;
        END IF;
    END LOOP;

    CLOSE cur1;
END
\\
DELIMITER ;

Подробности см. В руководстве: https://dev.mysql.com/doc/refman/5.7/en/cursors.html

Конечно, если возможно, я бы использовал INSERT ON DUPLICATE UPDATE, как уже упоминалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...