postgresql多功能事务控制

问题描述 投票:0回答:1

我创建了 4 个 postgresql 模拟函数,用于测试具有多个函数的事务控制,如下所示,

create table test
(
    text varchar(20)
);

create table log
(
    text varchar(20)
);

create or replace function test1
(
    p_data       in text,
    p_result     out text
)
as $$
begin

    insert into test (text)
    values(1);   

    p_result := '';                

exception
        when others then

          PERFORM log_entry
                (
                  'test1 error'
                );         
                
          p_result := '';  

end
$$ LANGUAGE plpgsql;

create or replace function test2
(
    p_data       in text,
    p_result     out text
)
as $$
begin

    insert into test (text)
    values(2);

    p_result := '';   

exception
        when others then
            
            PERFORM log_entry
                (
                  'test2 error'
                );
          
            p_result := '';     
           
end;
$$ LANGUAGE plpgsql;

create or replace function test3
(
    p_data       in text,
    p_result     out text
)
as $$
begin

    insert into test (text)
    values(3333333333333333333333333333333333333333333333333333333333333333333);

    p_result := ''; 

exception
        when others then

            PERFORM log_entry
                (
                  'test3 error'
                );
            
            p_result := '';  
end;
$$ LANGUAGE plpgsql;

create or replace function log_entry
(
    p_data       in text
)
returns void as $$
 
begin


    insert into log (text)
    values(p_data);

end;
$$ LANGUAGE plpgsql;

我调用函数的方式是,

DO $$ BEGIN

    PERFORM "test1"('');
    PERFORM "test2"('');
    PERFORM "test3"('');

END $$;

因此,当函数“test3”执行时,由于它尝试插入到测试表中的数据太长而失败,我可以看到表 test 有 2 行,值 1 和 2;并且表日志有 1 行,值 test3 错误。

我的问题是,

如果我想要实现的是,回滚由函数test1和test2完成的事务,但只提交日志条目(意味着表test应该为空,并且表日志应该有1行是test3错误),该怎么做那?

注意:我不想将3个函数合并为1个,因为在实际情况下,参数输入太多,几乎有100个输入,函数签名太大,而且我也不想使用dblink。

非常感谢。

postgresql function transactions procedure
1个回答
0
投票

无需进行一行修改即可实现这一目标。您必须重新设计代码。

一种可能性是向包含日志消息的函数添加另一个输出参数。那么代码可能是这样的:

DO
$$DECLARE
   result text;
   errmsg text;
BEGIN
   SELECT test1(NULL) INTO result, errmsg;
   IF errmsg IS NOT NULL THEN
      RAISE EXCEPTION '%', errmsg;
   END IF;

   SELECT test2(NULL) INTO result, errmsg;
   IF errmsg IS NOT NULL THEN
      RAISE EXCEPTION '%', errmsg;
   END IF;

   SELECT test2(NULL) INTO result, errmsg;
   IF errmsg IS NOT NULL THEN
      RAISE EXCEPTION '%', errmsg;
   END IF;
EXCEPTION
   WHEN raise_exception THEN
      GET STACKED DIAGNOSTICS errmsg := MESSAGE_TEXT;
      PERFORM log_entry(errmsg);
END;$$;
© www.soinside.com 2019 - 2024. All rights reserved.