繁体   English   中英

PostGreSQL - 控制事务

[英]PostGreSQL - Controlling transactions

我有一个存储过程,它依次调用其他几个存储过程; 它们每个都返回 true 或 false,并通过将它们存储到表中来在内部处理错误。

像这样的东西:

-- (MAIN STORED PROCEDURE)
BEGIN
 CALL STORED_PROC_1('WW','TT','FF',result);
 IF result = TRUE then
    CALL STORED_PROC_2('a','b','c',result);
    ...
 END IF;
END;

IF result != TRUE THEN
 ROLLBACK;
ELSE
 COMMIT;
END IF;

-- (END MAIN STORED PROCEDURE)

-------
--Example of Stored Procedure 1
CREATE OR REPLACE PROCEDURE STORED_PROC_1 (IN a TEXT, IN b TEXT, IN c TEXT, INOUT result boolean)
AS $BODY$
BEGIN

 -- DO SOME STUFF HERE

 IF ERROR_FOUND THEN
   INSERT INTO ERROR_LOG VALUES ('Error','Type of Error',CURRENT_DATE);
   --COMMIT; (I cannot do this commit here but I would like to save the information going into the ERROR_LOG table)
   result := FALSE;
 ELSE
   result := TRUE;
 END IF;
END;
$BODY$;

这实际上是我想要的; 仅在所有返回 TRUE 时提交; 问题是,在 STORED_PROC_1 或 _2 内部有写入错误日志表的错误处理,如果有错误,它们将在结果中返回 FALSE,然后将调用回滚,我将失去我的错误日志。

有没有办法创建一种可以加载错误信息并在 ROLLBACK 后写入的内存表? 或者有没有更好的方法来实现这一目标?

非常感谢。

如果可以的话,我建议使用FUNCTION而不是PROCEDURE ,因为它们在某种意义上内置了事务控制。 如果FUNCTION失败,您会自动回滚其事务。

话虽如此,我不会直接执行插入操作,而是创建一个如下所示的函数:

CREATE OR REPLACE FUNCTION func_logerror(error TEXT, errortype TEXT, date DATE DEFAULT CURRENT_DATE)
RETURNS SETOF ERROR_LOG
AS $$
DECLARE
BEGIN
    RETURN QUERY
    INSERT INTO ERROR_LOG VALUES (error, errortype, date) RETURNING *;
END;
$$;

根据您是否想要调用函数中的结果,使用SELECTPERFORM调用它。

PERFORM * FROM func_logerror('Error', 'Type of Error', CURRENT_DATE);

阅读您的回答后,我想出了这个来帮助澄清。 我建议根本不使用存储过程。 而是以不同的方式处理您的错误情况:

-- (MAIN STORED PROCEDURE)
CREATE OR REPLACE FUNCTION FUNC_MAIN()
RETURNS boolean
AS $$
DECLARE
    res    boolean;
BEGIN
    SELECT * INTO res FROM FUNC_1('WW','TT','FF');
    IF res = TRUE
    THEN
        SELECT * INTO res FROM FUNC_2('a','b','c');
        ...
    ELSE
        RETURN FALSE;
    END IF;
    RETURN res;
END;
$$;
-- (END MAIN STORED PROCEDURE)

-------
--Example of Stored Procedure 1
CREATE OR REPLACE FUNCTION FUNC_1 (a TEXT, b TEXT, c TEXT)
RETURNS boolean
AS $$
DECLARE
BEGIN
    -- ****complete data validation before writing to tables****
    -- If you hit any invalid data return out of the function before writing any persistent data
    -- Ex:
    IF COALESCE(a, '') = '' -- could be anything that may produce ERROR_FOUND from your example
    THEN
        RAISE WARNING 'FUNC_1 | param: a: must have a value'; 
        PERFORM * FROM "Schema".func_errlog('Error','Type of Error',CURRENT_DATE);
        RETURN FALSE;
    END IF;

    RETURN TRUE; -- If you've made it to the end of the function there should be no errors
END;
$$;

好的,这里是现在的样子。

-- (MAIN STORED PROCEDURE)
BEGIN
 CALL STORED_PROC_1('WW','TT','FF',result);
 IF result = TRUE then
    CALL STORED_PROC_2('a','b','c',result);
    ...
 END IF;
END;

IF result != TRUE THEN
 ROLLBACK;
ELSE
 COMMIT;
END IF;

-- (END MAIN STORED PROCEDURE)

-------
--Example of Stored Procedure 1
CREATE OR REPLACE PROCEDURE STORED_PROC_1 (IN a TEXT, IN b TEXT, IN c TEXT, INOUT result boolean)
AS $BODY$
BEGIN

 -- DO SOME STUFF HERE

 IF ERROR_FOUND THEN
   PERFORM * FROM "Schema".func_errlog('Error','Type of Error',CURRENT_DATE);
        IF FOUND
        THEN
          result := FALSE;
        END IF; 
 ELSE
   result := TRUE;
 END IF;
END;
$BODY$;

该函数基本上是您在此处提供的函数的副本。 所以,我仍然有同样的错误。 在 Main 过程中,如果我调用 ROLLBACK(由于错误,我想回滚所有内容,但我想保存错误并且函数确实保存了它,但它随后会受到 ROLLBACK 的影响......我是做错了什么?根据我的理解,这现在应该可以工作了......感谢您的支持。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM