昨天我发现了一件非常有趣(而且意想不到的)的事情。我被赋予了一个任务(在生产环境中)来更新TableA的三列(由于某些明显的原因,我正在改变表和列名),通过获取dummytable中存在的所有值。这两个表的主键是A列。我知道这个任务很简单,可以通过多种方式完成,但我选择为此编写一个存储过程(如下所示)。
当存储过程完成执行时,则注意到列B,C& statusCode具有相同的值(即,数千个记录在这三列中具有相同的值)。谁能告诉我出了什么问题?
1)此存储过程中有什么问题(或缺失)? (虚拟表也有数千条记录) 2)除了创建存储过程之外,还有什么可能是完成此任务的最佳方法?
PS:我使用MySQL工作台在生产环境中创建(执行了)这个存储过程,并且在执行过程中遇到了一个异常,它说明了“与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
答案 0 :(得分:1)
关于你的第一个问题:
1)此存储过程中有什么问题(或缺失)? (假表有 成千上万的记录)
我猜您忘了CLOSE
CURSOR
。在您结束LOOP
之后,您应该CLOSE
CURSOR
。
END LOOP claimlistloop;
CLOSE claimlist;
END
2)除了以外,有什么可能是完成这项任务的最佳方式 创建存储过程?
在STORED PROCEDURE
中执行此操作应该没问题。并且使用CURSOR
也没关系,因为你只需要执行一次程序(我猜因为这是一个生产修正)。
但是,根据您的问题,您只想根据提供的TableA
更新DummyTable
。我假设这些表具有相同的列。
所以我认为此查询优于CURSOR
:
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 :(得分:1)
忘记光标。事实上,如果可以避免,你永远不应该使用游标。游标非常慢。
简单地做
UPDATE
yourTable yt
INNER JOIN dummyTable dt ON yt.A = dt.A
SET
yt.B = dt.B,
yt.C = dt.C;
你没事。
答案 2 :(得分:1)
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 ... END
阻止
这是 SQLFiddle 演示。