postgreSQL异常后如何重试事务
在我的代码的不同部分,我必须在异常后重试事务。但我不知道该怎么做。 这是我的测试功能:
CREATE OR REPLACE FUNCTION f() RETURNS VOID AS $$
DECLARE
user_cur CURSOR FOR SELECT * FROM "user" WHERE id < 50 limit 10;
row RECORD;
counter INTEGER DEFAULT 0;
dummy INTEGER DEFAULT 0;
BEGIN
RAISE INFO 'Start... ';
OPEN user_cur;
LOOP
FETCH user_cur INTO row;
EXIT WHEN row IS NULL;
BEGIN
UPDATE "user" SET dummy = 'dummy' WHERE id = row.id;
counter := counter + 1;
dummy := 10 / (5 % counter);
RAISE NOTICE 'dummy % , user_id %', (5 % counter), row.id;
EXCEPTION WHEN division_by_zero THEN
--What should I do here to retry transaction?
END;
END LOOP;
RAISE INFO 'Finished.';
RETURN;
END;
$$ LANGUAGE plpgsql;
In different parts of my code I have to retry transactions after exceptions. But I cant figure out how to do it.
Here is my test function:
CREATE OR REPLACE FUNCTION f() RETURNS VOID AS $
DECLARE
user_cur CURSOR FOR SELECT * FROM "user" WHERE id < 50 limit 10;
row RECORD;
counter INTEGER DEFAULT 0;
dummy INTEGER DEFAULT 0;
BEGIN
RAISE INFO 'Start... ';
OPEN user_cur;
LOOP
FETCH user_cur INTO row;
EXIT WHEN row IS NULL;
BEGIN
UPDATE "user" SET dummy = 'dummy' WHERE id = row.id;
counter := counter + 1;
dummy := 10 / (5 % counter);
RAISE NOTICE 'dummy % , user_id %', (5 % counter), row.id;
EXCEPTION WHEN division_by_zero THEN
--What should I do here to retry transaction?
END;
END LOOP;
RAISE INFO 'Finished.';
RETURN;
END;
$ LANGUAGE plpgsql;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于您想要做的事情, 循环内循环将是一个正确的解决方案。无需昂贵的异常处理。
测试设置:
函数:
调用:
输出:
您的代码示例显示了许多问题:
不要使用保留字作为标识符。
user
是每个 SQL 中的保留字标准,尤其是 PostgreSQL。将您的表称为“用户”是不好的做法。双引号使其成为可能。但这并不意味着这是一个好主意。不要声明与函数体中使用的表列同名的变量。这很容易导致命名冲突。在您的示例中,
dummy
同时是一个变量和列名。只是另一把装满子弹的脚枪。一种(任意)可能性是在变量前加上_
前缀,就像我演示的那样。A
FOR< /code> 循环
就像我演示的那样比显式光标处理简单得多。
For what you are trying to do, a LOOP inside the LOOP would be a proper solution. No need for expensive exception handling.
Test setup:
Function:
Call:
Output:
Your code example displays a number of problems:
Don't use reserved words as identifiers.
user
is a reserved word in every SQL standard and in PostgreSQL in particular. It is bad practice to call your table "user". The double-quotes make it possible. Doesn't mean it's a good idea, though.Don't declare variables of the same name as table columns you use in the function body. That leads to naming conflicts very easily.
dummy
is a variable and a column name at the same time in your example. Just another loaded foot gun. One (arbitrary) possibility is to prefix variables with a_
like I demonstrate.A
FOR
loop like I demonstrate is much simpler than explicit cursor handling.感谢以上评论,我找到了解决方案:
Thanks to the above comments I've found the solution: