【问题标题】:Why does mysql not allow to fetch into user-defined variable in cursor?为什么mysql不允许在游标中获取用户定义的变量?
【发布时间】:2014-11-21 02:04:45
【问题描述】:

我有这样的代码和 mysql 发布错误:

该行:FETCH cur_recycle_batch INTO @id, @created_by, @created_date; 发布错误。

有人知道为什么mysql不允许获取用户定义的变量吗?

CREATE DEFINER=`root`@`localhost` PROCEDURE `generate_row`()
BEGIN

    DECLARE done TINYINT DEFAULT FALSE;
    DECLARE cur_recycle_batch CURSOR FOR SELECT 
                                                id, created_by, created_date
                                            FROM
                                                outsourcing_recycle_batch
                                            order by created_date;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    START transaction;

        OPEN cur_recycle_batch;

            insert_loop : loop

                FETCH cur_recycle_batch INTO @id, @created_by, @created_date;

                IF done THEN

                    LEAVE insert_loop;
                END IF;

                INSERT INTO `test_db`.`outsourcing_recycle_batch_history_list`
                (`outsourcing_recycle_batch_pk`,
                `outsourcing_history_pk`,
                `created_by`,
                `created_by_full_name`,
                `created_date`)
                VALUES
                (@id,
                1,
                @created_by,
                'AAAAAAAA',
                @created_date);


            END LOOP;

        CLOSE cur_recycle_batch;

    commit;

END

【问题讨论】:

  • 基本上这似乎是一个设计问题。在这种情况下使用9.4 User-Defined Variables 有什么特别的原因吗?还要检查函数:LAST_INSERT_ID.
  • 我在我的问题中使用了声明变量。我最初使用用户定义的变量是为了节省几行代码,但我只是好奇为什么 mysql 不允许这样做。 LAST_INSERT_ID 在这种情况下是可以的。感谢您的建议。

标签: mysql stored-procedures database-cursor


【解决方案1】:

有一个解决方法:DECLARE 局部变量而不是依赖用户变量。

CREATE DEFINER=`root`@`localhost` PROCEDURE `generate_row`()
BEGIN
    DECLARE local_id INT;
    DECLARE local_created_by VARCHAR(20);
    DECLARE local_created_date DATE;
    DECLARE done TINYINT DEFAULT FALSE;
    DECLARE cur_recycle_batch CURSOR FOR SELECT id, created_by, created_date
                                            FROM outsourcing_recycle_batch
                                            ORDER BY created_date;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    START transaction;
        OPEN cur_recycle_batch;
            insert_loop : loop
                FETCH cur_recycle_batch INTO local_id, local_created_by, local_created_date;
                IF done THEN
                    LEAVE insert_loop;
                END IF;
                INSERT INTO `test_db`.`outsourcing_recycle_batch_history_list`
                (`outsourcing_recycle_batch_pk`,
                `outsourcing_history_pk`,
                `created_by`,
                `created_by_full_name`,
                `created_date`)
                VALUES
                (local_id,
                1,
                local_created_by,
                'AAAAAAAA',
                local_created_date);
            END LOOP;
        CLOSE cur_recycle_batch;
    commit;
END

鉴于此解决方法,实现 FETCH INTO 用户变量一定不是优先事项。

根据您的示例,还有一个更简单的解决方法:根本不使用游标,只需使用 INSERT...SELECT 插入一组行。

CREATE DEFINER=`root`@`localhost` PROCEDURE `generate_row`()
BEGIN
    INSERT INTO `test_db`.`outsourcing_recycle_batch_history_list`
        (`outsourcing_recycle_batch_pk`,
        `outsourcing_history_pk`,
        `created_by`,
        `created_by_full_name`,
        `created_date`)
    SELECT id, 1, created_by, 'AAAAAAAA', created_date
    FROM outsourcing_recycle_batch;
END

我不知道您是否简化了示例。您可能需要使用游标对值进行其他逐行操作,而不是简单地插入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2013-05-08
    • 1970-01-01
    • 2011-09-04
    • 2011-03-01
    • 1970-01-01
    • 2016-08-10
    相关资源
    最近更新 更多