触发取消交易

Trigger to cancel transaction

我必须根据涉及四个 table 的相对复杂的查询来执行规则。如果 table 中的任何一个 updates/inserts/deletes,我需要 运行 相同的查询来检查是否应该拒绝该操作(通过抛出异常)。

我认为必须有四个单独的触发器,因为 CREATE TRIGGER 似乎只接受一个 "on" 子句;但我不想重复查询,而是将其保存在单独的存储过程中。

我想知道是否有一种方法可以为验证查询提供数据库状态的表示,就像在事件触发触发器之后一样;并让查询能够在需要时取消该事务,回滚到触发触发器之前的状态。我认为这不是 "before/for each row" 所做的;因为它使用 :new:old - 如果我要使用新行,我将不得不重写查询四次,用 new 代替每个 table.


改编后的答案:

即使我尽我最大的努力使自动提交处于打开状态,'after statement' 触发器也会做正确的事情;即在此块的底部没有选择任何行。

create or replace trigger test_after_tr
  after insert or update or delete on footable
begin
  raise_application_error(-20000, 'violated');
end;
/

set autocommit on;
begin
  execute immediate 'set autocommit on';
  insert into footable(name) values('fail');
exception when others then null;
end;
/

select * from footable where name = 'fail';

您可以在使用 "after statement" 触发器(即省略 for each row 子句)的语句后查看数据库状态。但是,您无权访问语句级触发器中的 oldnew。您可以检查 4 table 中没有数据违反您的规则(可能很慢),或者您可以在每个 table 上使用行级触发器将受影响记录的键记录在 PL/SQL 集合,然后您可以使用该集合在 "after statement" 触发器中执行更具选择性的查询。