【问题标题】:Trigger to cancel transaction触发取消交易
【发布时间】:2015-07-15 12:46:50
【问题描述】:

我必须根据涉及四个表的相对复杂的查询来强制执行规则。如果任何表更新/插入/删除,我需要运行相同的查询来检查是否应该拒绝操作(通过抛出异常)。

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

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


改编答案:

即使我尽我最大的努力将自动提交设置为开启,'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';

【问题讨论】:

  • 嗨,如果我理解正确,您有复杂的约束,需要检查和维护 4 个表。我的理解是正确的还是你给我举个例子更好地理解。
  • 这或多或少是对的(尽管它不是一个检查约束——因为检查约束是不够的)。
  • 只是一些开箱即用的问题:1)为什么数据存储在4个表中,如果所有4个表都是1 -1关系,那么它可以在单表中。 2)你能不能从这4个表中查看并触发查看
  • 他们不是一对一的关系。

标签: sql oracle triggers oracle11g transactions


【解决方案1】:

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

【讨论】:

  • 如果我使用“after statement”,是否已经为时已晚,无法通过抛出异常回滚?
  • @Reinderien - 在语句之后触发后触发器,而不是在事务结束之后 - 您仍然可以回滚以响应异常。
  • @AlexPoole 如果顶级调用者没有显式启动事务怎么办(在这种情况下,我认为这是一个单语句事务?)
  • @AlexPoole 好的。那么假设没有不合适的异常吞咽块,对于单个DML语句,默认的动作会是回滚?
  • 如果触发器(任何触发器)引发异常,则回滚语句
猜你喜欢
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 2019-07-27
  • 2014-06-26
  • 2014-01-22
  • 2011-08-12
  • 1970-01-01
  • 2021-12-18
相关资源
最近更新 更多