偶遇mysql8存儲過程中變量命名不當導致的bug

因需要對舊數據庫的數據進行遷移,某表某字段原先是多個值的逗號拼接,要拆分到另外一個表中以多行記錄的方式保存.

用存儲過程來處理, 就遇到了這麼個問題

與SQLSERVER的局部變量前加@符號不同, mysql變量前面可以不加任何符號, 這可能會導致mysql分不清是字段還是變量

演示代碼如下, 需要對字符串類型的字段title進行處理, 局部變量也是命名爲title.

USE `test`;
DROP TABLE IF EXISTS `infos`;
CREATE TABLE `infos`(
    `info_id` int NOT NULL,
    `title` varchar(2000) COMMENT '多個字符串的逗號拼接',
    PRIMARY KEY(`info_id`)
) ENGINE = InnoDB;
INSERT INTO `infos`(`info_id`, `title`)
VALUES(1, 'aben,sky');

DROP PROCEDURE IF EXISTS `mysp_a`;
DELIMITER $$
CREATE PROCEDURE `mysp_a`()
BEGIN
    # 定義變量
    DECLARE done INT DEFAULT 0;
    DECLARE id INT; #注意: 這裏也不能用info_id, 否則下面的sql分不清是變量還是字段, 根本不會返回數據(或許是因爲執行錯誤但是又沒有拋出錯誤)
    DECLARE title VARCHAR(2000);
    # 定義cursor
    DECLARE cursor1 CURSOR FOR
    SELECT `info_id`, `title` FROM `infos` WHERE `info_id` = 1;
    -- 遊標中的內容執行完後將done設置爲true
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    OPEN cursor1;
    FETCH cursor1 INTO id, title;
    WHILE done = 0 DO
        SELECT id AS `info_id`, title AS `title`; #這裏只是簡單演示, 看字段值能否提取出來.
        FETCH cursor1 INTO id, title;
    END WHILE;
    CLOSE cursor1;
END$$
DELIMITER ;

執行結果就是, int類型的id能獲取, 但是varchar類型的title是null:

mysql> CALL `mysp_a`();
+---------+-------+
| info_id | title |
+---------+-------+
|       1 | NULL  |
+---------+-------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

修正方法很簡單, 只要把這個varchar類型的變量名稱改掉就行, 比如: $title, title2等等都可以的, 本人建議前面加$符號

可以這樣改:

DROP PROCEDURE IF EXISTS `mysp_a`;
DELIMITER $$
CREATE PROCEDURE `mysp_a`()
BEGIN
    # 定義變量
    DECLARE done INT DEFAULT 0;
    DECLARE $info_id INT; #變量名前加前綴
    DECLARE $title VARCHAR(2000); #變量名前加前綴
    # 定義cursor
    DECLARE cursor1 CURSOR FOR
    SELECT `info_id`, `title` FROM `infos` WHERE `info_id` = 1;
    -- 遊標中的內容執行完後將done設置爲true
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    OPEN cursor1;
    FETCH cursor1 INTO $info_id, $title;
    WHILE done = 0 DO
        SELECT $info_id AS `info_id`, $title AS `title`; #這裏只是簡單演示, 看字段值能否提取出來.
        FETCH cursor1 INTO $info_id, $title;
    END WHILE;
    CLOSE cursor1;
END$$
DELIMITER ;

mysql變量名前面可以加$符號, 但是不支持MSSQL的@

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章