我想知道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')
是否会导致hello
在UserAccount
表中,而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';
型
2条答案
按热度按时间luaexgnf1#
函数总是在函数调用开始时处于活动状态的单个事务中运行,因此,要么所有语句都成功,要么所有语句都失败。这是可以保证的。
还有其他一些事情可能导致
INSERT
无效,例如返回NULL的行级BEFORE
触发器。3bygqnnd2#
是的,函数(PL/pgSQL functions和SQL functions)是原子的。函数在事务中运行,所以如果有错误,事务会回滚。
例如,您创建
my_func()
函数,将5
设置为my.var
,然后可能导致division by zero
错误,如下所示:字符串
首先,您将
2
设置为my.var
,然后调用my_func(1)
,然后5
成功设置为my.var
,如下所示:型
现在,您将
2
设置为my.var
,然后调用my_func(0)
,然后发生division by zero
错误,然后my.var
仍然是2
,如下所示,因为my_func()
函数被回滚:型