[英]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;
$$;
根据您是否想要调用函数中的结果,使用SELECT
或PERFORM
调用它。
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.