这里是 Postgres 8.4。想象此代码片段来自 Postgres 文档:
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Check that empname and salary are given
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname cannot be null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% cannot have null salary', NEW.empname;
END IF;
-- Who works for us when she must pay for it?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
END IF;
-- Remember who changed the payroll when
NEW.last_date := current_timestamp;
NEW.last_user := current_user;
RETURN NEW;
END;
$emp_stamp$ LANGUAGE plpgsql;
如果我们想做一些事情,比如记录自定义表,这些异常:
-- Check that empname and salary are given
IF NEW.empname IS NULL THEN
INSERT INTO my_log_table ('User didn't supplied empname')
RAISE EXCEPTION 'empname cannot be null';
END IF;
它不会起作用,因为我们在 a 之前放置的任何内容RAISE EXCEPTION
调用被回滚撤消RAISE EXCEPTION
意味着,即我们创建的 my_log_table 行将被删除RAISE EXCEPTION
叫做。
完成这样的事情的最佳方法是什么?也许捕获我们的自定义异常?
关闭回滚@TRIGGER不是一个选项,我需要它。
You can 陷阱错误/ 捕获异常。
In the EXCEPTION
阻止您可以执行其他任何操作,例如 INSERT 到另一个表中。之后,您可以重新引发异常以传播出去,但这会回滚整个事务,包括对日志表的插入(除非异常被包装并捕获在外部函数中)。
You could:
或者,您也可以取消该行触发了触发函数并且not引发异常。交易中的其他一切都正常进行。
假设这是一个触发器ON UPDATE
并且您有另一个具有相同结构的表来将失败的 INSERT 写入到:
CREATE OR REPLACE FUNCTION emp_stamp()
RETURNS trigger AS
$func$
BEGIN
-- Check that empname and salary are given
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname cannot be null';
END IF;
IF ...
RETURN NEW; -- regular end
EXCEPTION WHEN others THEN -- or be more specific
INSERT INTO log_tbl VALUES (NEW.*); -- identical table structure
RETURN NULL; -- cancel row
END
$func$ LANGUAGE plpgsql;
注意NEW
包含异常发生之前行的状态,包括同一函数中先前成功的语句。
Trigger:
CREATE TRIGGER emp_stamp
BEFORE INSERT OR UPDATE ON tbl
FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)