产生错误结果的MySql过程
昨天我注意到一件非常有趣(也出乎意料)的事情。我的任务是(在生产环境中)通过获取dummytable中的所有值来更新TableA的三列(由于一些明显的原因,我正在更改表和列名)。这两个表的主键都是A列。我知道这项任务非常简单,可以通过多种方式完成,但我选择为此编写一个存储过程(如下所示) 当存储过程完成执行时,会注意到B、C和statusCode列具有相同的值(即,数千条记录在这三列中具有相同的值)。有人能告诉我出了什么问题吗 1) 此存储过程中有什么错误(或缺失)?(虚拟表也有数千条记录) 2) 除了创建存储过程之外,执行此任务的最佳方法是什么 PS:我使用MySQL workbench在生产环境中创建(也执行)了这个存储过程,在执行过程中出现了一个异常,该异常表示“与MySQL服务器的连接丢失”但是我想,因为我在远程机器上运行这个过程,所以当这个过程执行时,服务器上没有中断 这是我的存储过程产生错误结果的MySql过程,mysql,sql,stored-procedures,Mysql,Sql,Stored Procedures,昨天我注意到一件非常有趣(也出乎意料)的事情。我的任务是(在生产环境中)通过获取dummytable中的所有值来更新TableA的三列(由于一些明显的原因,我正在更改表和列名)。这两个表的主键都是A列。我知道这项任务非常简单,可以通过多种方式完成,但我选择为此编写一个存储过程(如下所示) 当存储过程完成执行时,会注意到B、C和statusCode列具有相同的值(即,数千条记录在这三列中具有相同的值)。有人能告诉我出了什么问题吗 1) 此存储过程中有什么错误(或缺失)?(虚拟表也有数千条记录) 2
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语句,两个表的部分都被读取,一些指向内存地址的指针被交换并写回磁盘。非常快,很好。谢谢(彼得)因为凯尔先回答了问题,所以他的回答被接受了。谢谢(彼得)因为凯尔先回答了问题,所以他的回答被接受了。