首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SELECT INTO with SELECT FOR UPDATE in PostgreSQL

SELECT INTO with SELECT FOR UPDATE in PostgreSQL
EN

Stack Overflow用户
提问于 2014-10-05 01:32:59
回答 1查看 925关注 0票数 3

假设我有一个message关系,其中我保存了使用以下命令创建的消息:

代码语言:javascript
复制
CREATE TABLE message 
(
     id serial primary key, 
     foo1 integer, 
     foo2 integer, 
     foo3 text
)

我们有一个函数可以获取一条消息并将其从关系中删除,如下所示:

代码语言:javascript
复制
CREATE FUNCTION get_and_delete_message(p_foo1 integer)
RETURNS TABLE(r_id integer, r_foo1 integer, r_foo2 integer, r_foo3 text) AS $$
DECLARE
  message_id integer;
BEGIN
    SELECT id INTO message_id FROM message WHERE foo1 = p_foo1 LIMIT 1;
    RETURN QUERY SELECT * FROM message WHERE foo1 = p_foo1 LIMIT 1;
    DELETE FROM message where id = message_id;
END;
$$ LANGUAGE plpgsql;

假设READ_COMMITTED隔离级别,可能是来自两个用户的两个并发事务返回相同的消息,尽管显然只有一个用户删除/获取该消息。这不是我的应用程序所期望的行为,我希望只有一个用户可以读取一条消息。

假设REPEATABLE_READ不会发生这种情况。

但在阅读了有关FOR UPDATE的内容后,我认为也许仍然可以使用READ_COMMITTED级别并按如下方式更改get_and_delete_message函数:

代码语言:javascript
复制
   ...
    BEGIN
        SELECT id INTO message_id FROM message WHERE foo1 = p_foo1 LIMIT 1;
        RETURN QUERY SELECT * FROM message WHERE foo1 = p_foo1 LIMIT 1 FOR UPDATE;
        DELETE FROM message where id = message_id;
    END;
    ...

据我所知,在第二个SELECT中使用FOR UPDATE实际上会锁定返回的行,直到事务结束,所以如果我们有两个并发事务,那么实际上只有一个事务会返回并删除消息。

真的是这样吗?或者我也应该做SELECT id INTO message_id FROM message WHERE foo1 = p_foo1 LIMIT 1 FOR UPDATE?我找不到任何关于结合使用SELECT INTOFOR UPDATE的信息。对此有什么想法吗?

EN

回答 1

Stack Overflow用户

发布于 2014-10-05 02:08:45

您可以在单个语句中做到这一点,不需要select:

代码语言:javascript
复制
CREATE FUNCTION get_and_delete_message(p_foo1 integer)
RETURNS TABLE(r_id integer, r_foo1 integer, r_foo2 integer, r_foo3 text) 
AS $$
  DELETE FROM message 
    where foo1 = p_foo1 
  returning *;
END;
$$ LANGUAGE sql;

这将删除行,然后返回所有删除的行作为delete语句的结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26195339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档