Postgres - 如果记录未找到,则在更新时返回错误

28

我想知道在执行更新时,如果数据库中不存在该行记录,是否有办法返回错误信息。

update users set email='aa@bb.com' where id=200

如果用户表中没有id为200的用户,那么Postgres只会返回“UPDATE 0”。然而,我想知道是否可以得到一个错误提示。这样一来,我就不需要向数据库发出两个请求,一次用于检查存在性,一次用于更新。如果我们分开进行操作,则还可能存在检查存在性和发出更新之间的竞争条件。

我为什么需要一个错误提示?很简单——让客户端知道他们使用了无效的用户ID,并采取纠正措施。


你的问题并不是非常清楚。如果记录不存在,你想要采取什么行动?插入一个新的记录,还是简单地通知用户/重定向到登录页面? - Patrick
1
这是一个更新语句。因此,客户端期望记录存在。但可能在客户端发出更新之前已被删除。应通知发出更新的客户端记录不存在。无需插入任何新记录。 - sat
1
与其抛出异常,最好在编程语言中简单地检查更新的行数(正如Igor所建议的那样),这样更有效率。 - user330315
2个回答

25

你可以使用类似以下的方法

update users set email='aa@bb.com' where id=200 returning id;

这个查询会返回更新行的id。如果返回0行,则在您的应用程序中抛出错误。

另外,您可能还想检查您的数据库驱动程序/框架是否返回受影响行数的计数(例如JDBC中的getUpdateCount())。


听起来像是一个更高效的解决方案。这个方法也适用于多行更新吗? - sat
@BVSat 是的。它将返回所有更新行的 id。有关详细信息和示例,请查阅文档:http://www.postgresql.org/docs/current/static/sql-update.html - Ihor Romanchenko

13

您可以使用匿名代码块。

do $$
begin
    update users set email='aa@bb.com' where id=200;
    if not found then raise exception 'User not found';
    end if;
end $$;

或常规函数:

create or replace function update_user(new_email text, user_id integer)
returns void language plpgsql 
as $$
begin
    update users set email = new_email where id = user_id;
    if not found then raise exception 'User id % not found', user_id;
    end if;
end $$;    

select update_user('aa@example.com', 200);

太棒了!非常感谢。有没有办法将其概括,以便我们不必为所有表格编写此代码?例如,我们如何更改错误消息以将表格名称单数化,而不是在“未找到用户”中使用“用户”。我们可以将其制作成一个函数吗?或者,我们可以将其设置为特定模式下所有表格的更新命令的默认操作吗? - sat
你应该将每个更新查询替换为匿名代码块,就像答案中所示。 - klin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接