0
DO $$
BEGIN
raise notice '%', (SELECT * from public.clientcalledthisfunction(1,2));
END $$;

CREATE OR REPLACE FUNCTION  public.clientcalledthisfunction(userid1_ integer, userid2_ integer)
RETURNS integer
AS $$
DECLARE
result integer;
BEGIN
result:=(SELECT  * from public.call_updatedata(userid1_, userid2_)) ;
RETURN result;
EXCEPTION WHEN others THEN
End $$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION public.call_updatedata(userid1_ integer, userid2_ integer)
RETURNS integer
AS $$
DECLARE
userdata_1 integer;
userdata_2 integer;
userdata_total integer;
BEGIN

SELECT * FROM public.updatedata(userid1_) INTO userdata_1;

SELECT * FROM public.updatedata(userid2_) INTO userdata_2;

userdata_total:=(userdata_1 + userdata_2);
RETURN userdata_total;
EXCEPTION WHEN others THEN
End $$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION public.updatedata(userid_ integer)
RETURNS integer
AS $$
DECLARE
userdata_ integer;
BEGIN

LOOP
SET  TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN
SAVEPOINT foo;

SELECT userdata FROM public.footable WHERE userid=userid_ INTO userdata_;

UPDATE public.footable SET userdata = userdata_ + 1 WHERE userid=userid_ ;

EXIT ;
EXCEPTION WHEN others THEN
    ROLLBACK TO SAVEPOINT foo;
END;
END LOOP;
RETURN userdata_ + 1;
EXCEPTION WHEN others THEN
END $$ language plpgsql;

客户端calls public.clientcalledthisfunction()功能;

我需要在函数中实现 ISOLATION LEVEL SERIALIZABLESELECT + UPDATE因为我不想“丢失更新” ...updatedata()我只想.public.updatedata function()

updatedata()如果出现异常,则在函数中;我希望它回滚并再次通过循环savepoint foo重试过程......select + update

但我会error"control reached end of function without RETURN"......我不明白问题出在哪里。

4

2 回答 2

0

我只想在 public.updatedata 函数()中设置 SERIALIZABLE 隔离级别。

你不能。隔离是事务级别的属性。

如果出现异常,则在 updatedata() 函数中;我希望它回滚到保存点 foo

您可以为此使用BEGIN ... EXCEPTION ...块。

但是,如果您使用可序列化隔离,这实际上不会起作用,因为某些序列化失败只能在提交时发现。

于 2017-01-06T13:38:37.770 回答
0

在您拥有的每个功能中

EXCEPTION WHEN others THEN
End

在最后。如果发生任何异常,则触发这段代码。而且由于之后没有声明,它会因错误return而崩溃。"control reached end of function without RETURN"

分析这些异常,您将确切知道发生了什么。或者更好的是,只需删除这些行。毕竟EXCEPTION WHEN others是万恶之源。


编辑:经过一番搜索,您似乎无法更改函数内的隔离级别。毕竟调用函数是一个查询,并且必须在任何查询之前设置隔离级别。

于 2017-01-06T11:25:22.217 回答