首页 > 解决方案 > plpgsql 函数是原子的吗?

问题描述

我想知道plpgsql函数调用的原子性以及嵌套调用:

例如,我想将两条信息放入两个不同的表中:

CREATE OR REPLACE FUNCTION email_registration(
  i_email TEXT,
  i_nickname TEXT
) RETURNS JSONB AS $$
BEGIN
  DECLARE
    o_account "UserAccount";
    o_identity "UserIdentity";
  BEGIN
    INSERT INTO "UserAccount"  (nickname) VALUES (i_nickname) RETURNING * INTO o_account;
    INSERT INTO "UserIdentity" (email) VALUES (i_email) RETURNING * INTO o_identity;
    RETURN jsonb_build_object(
        'account',row_to_json(o_account), 
         'identity',row_to_json(o_identity)
    );
  END;
END;
$$ LANGUAGE 'plpgsql'; 

调用email_registration('hello', 'world')是否会导致出现helloUserAccount表中并world在表中丢失UserIdentity


另外,如果将两个插入重构到函数中,函数调用仍然是原子的吗?

IE。

CREATE OR REPLACE FUNCTION email_registration(
  i_email TEXT,
  i_nickname TEXT
) RETURNS JSONB AS $$
BEGIN
  DECLARE
    o_account "UserAccount";
    o_identity "UserIdentity";
  BEGIN
    o_account := insert_email(i_email);
    o_identity := insert_nickname(i_nickname);
    RETURN jsonb_build_object(
        'account',row_to_json(o_account), 
         'identity',row_to_json(o_identity)
    );
  END;
END;
$$ LANGUAGE 'plpgsql'; 

标签: postgresql

解决方案


函数始终在启动函数调用时处于活动状态的单个事务中运行,因此要么所有语句都成功,要么所有语句都失败。这是有保证的。

还有其他可能导致INSERT无效的事情,例如BEFORE返回 NULL 的行级触发器。


推荐阅读