产生错误结果的MySql过程

产生错误结果的MySql过程,mysql,sql,stored-procedures,Mysql,Sql,Stored Procedures,昨天我注意到一件非常有趣(也出乎意料)的事情。我的任务是(在生产环境中)通过获取dummytable中的所有值来更新TableA的三列(由于一些明显的原因,我正在更改表和列名)。这两个表的主键都是A列。我知道这项任务非常简单,可以通过多种方式完成,但我选择为此编写一个存储过程(如下所示) 当存储过程完成执行时,会注意到B、C和statusCode列具有相同的值(即,数千条记录在这三列中具有相同的值)。有人能告诉我出了什么问题吗 1) 此存储过程中有什么错误(或缺失)?(虚拟表也有数千条记录) 2

昨天我注意到一件非常有趣(也出乎意料)的事情。我的任务是(在生产环境中)通过获取dummytable中的所有值来更新TableA的三列(由于一些明显的原因,我正在更改表和列名)。这两个表的主键都是A列。我知道这项任务非常简单,可以通过多种方式完成,但我选择为此编写一个存储过程(如下所示)

当存储过程完成执行时,会注意到B、C和statusCode列具有相同的值(即,数千条记录在这三列中具有相同的值)。有人能告诉我出了什么问题吗

1) 此存储过程中有什么错误(或缺失)?(虚拟表也有数千条记录) 2) 除了创建存储过程之外,执行此任务的最佳方法是什么

PS:我使用MySQL workbench在生产环境中创建(也执行)了这个存储过程,在执行过程中出现了一个异常,该异常表示“与MySQL服务器的连接丢失”但是我想,因为我在远程机器上运行这个过程,所以当这个过程执行时,服务器上没有中断

这是我的存储过程

DELIMITER $$

CREATE DEFINER=`ABC`@`%` PROCEDURE `RetrieveExtractionData`()

BEGIN

DECLARE claimlisttraversed BOOLEAN DEFAULT FALSE;

DECLARE a VARCHAR(20);

DECLARE b INTEGER;

DECLARE c INTEGER;


DECLARE claimlist CURSOR FOR SELECT
`dummytable`.`A`,
`dummytable`.`B`,
`dummytable`.`C`
FROM `ABC`.`dummytable`;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET claimlisttraversed = TRUE;


OPEN claimlist;

claimlistloop: LOOP

    FETCH claimlist INTO a, b, c;

    IF claimlisttraversed THEN
        CLOSE claimlist;
        LEAVE claimlistloop;
    END IF;
    UPDATE `ABC`.`TableA`
SET
`B` = b,
`C` = c,
`statuscode` = 'Sent'
WHERE `A` = a;

END LOOP claimlistloop;

END

关于你的第一个问题:

1) 此存储过程中有什么错误(或缺失)?(虚拟表已安装。) (还有数千条记录)

我猜你忘了关闭
光标
。在结束
循环
之后,您应该
关闭
光标

END LOOP claimlistloop;

CLOSE claimlist;

END
2) 除此之外,完成这项任务的最佳方式是什么 创建存储过程

存储过程中执行此操作应该可以。另外,使用
游标
也可以,因为您只需执行一次过程(我想这是一个生产修复)

但是根据您的问题,您只需要根据提供的
DummyTable
更新
TableA
。我假设这些表具有相同的列

因此,我认为这个查询比
光标
更好:

UPDATE TableA A
    INNER JOIN DummyTable D ON D.A = A.A
    SET A.B = D.B
        , A.C = D.C
        , A.statuscode = 'Sent';

但请先在备份或虚拟表上尝试。我还没有测试过它。

关于你的第一个问题:

1) 此存储过程中有什么错误(或缺失)?(虚拟表已安装。) (还有数千条记录)

我猜你忘了关闭
光标
。在结束
循环
之后,您应该
关闭
光标

END LOOP claimlistloop;

CLOSE claimlist;

END
2) 除此之外,完成这项任务的最佳方式是什么 创建存储过程

存储过程中执行此操作应该可以。另外,使用
游标
也可以,因为您只需执行一次过程(我想这是一个生产修复)

但是根据您的问题,您只需要根据提供的
DummyTable
更新
TableA
。我假设这些表具有相同的列

因此,我认为这个查询比
光标
更好:

UPDATE TableA A
    INNER JOIN DummyTable D ON D.A = A.A
    SET A.B = D.B
        , A.C = D.C
        , A.statuscode = 'Sent';

但请先在备份或虚拟表上尝试。我还没有测试它。

忘记光标。事实上,如果光标是可以避免的,就不应该使用它。光标速度非常慢

干脆

UPDATE 
yourTable yt
INNER JOIN dummyTable dt ON yt.A = dt.A
SET
yt.B = dt.B,
yt.C = dt.C;

你很好。

忘记光标。事实上,如果光标是可以避免的,就不应该使用它。光标速度非常慢

干脆

UPDATE 
yourTable yt
INNER JOIN dummyTable dt ON yt.A = dt.A
SET
yt.B = dt.B,
yt.C = dt.C;
你很好

1) 此存储过程中有什么错误(或缺失)?(虚拟表) 也有数千条记录)
2) 什么可能是最好的 除了创建存储过程之外,还有什么方法可以完成此任务

我想,你目前缺少的最重要的一点是,你不需要任何游标。整个存储过程是一条
UPDATE
语句。单独执行或将其包装在存储过程中

CREATE PROCEDURE RetrieveExtractionData()
UPDATE TableA a JOIN dummytable d
    ON a.a = d.a
   SET a.b = d.b, a.c = d.c, a.statuscode = 'Sent'; 
您甚至不需要更改分隔符并使用
BEGIN。。。结束

这里是演示

1) 此存储过程中有什么错误(或缺失)?(虚拟表) 也有数千条记录)
2) 什么可能是最好的 除了创建存储过程之外,还有什么方法可以完成此任务

我想,你目前缺少的最重要的一点是,你不需要任何游标。整个存储过程是一条
UPDATE
语句。单独执行或将其包装在存储过程中

CREATE PROCEDURE RetrieveExtractionData()
UPDATE TableA a JOIN dummytable d
    ON a.a = d.a
   SET a.b = d.b, a.c = d.c, a.statuscode = 'Sent'; 
您甚至不需要更改分隔符并使用
BEGIN。。。结束


这是演示。

谢谢您的回复,但是您能解释一下为什么光标在这个特定的实例中会变慢吗?不仅在这个特定的实例中,它们总是非常慢。解释为什么会深入源代码。但是光标会首先读取整个虚拟表并将其保存在内存中。然后逐行执行update语句。而使用简单的update语句,两个表的部分都被读取,一些指向内存地址的指针被交换并写回磁盘。非常快。谢谢你的回复,但是你能解释一下为什么光标在这个特定的例子中会变慢吗?不仅在这个特定的例子中,他们总是非常慢。解释为什么会深入源代码。但是光标会首先读取整个虚拟表并将其保存在内存中。然后逐行执行update语句。而使用简单的update语句,两个表的部分都被读取,一些指向内存地址的指针被交换并写回磁盘。非常快,很好。谢谢(彼得)因为凯尔先回答了问题,所以他的回答被接受了。谢谢(彼得)因为凯尔先回答了问题,所以他的回答被接受了。