Oracle:事务内的触发器(2条语句)

Oracle:事务内的触发器(2条语句),oracle,transactions,triggers,oracle10g,Oracle,Transactions,Triggers,Oracle10g,我正在处理Oracle 10g DB,事务中的触发器有问题。 表A有3个触发器:一个在插入之前,一个在更新之前,最后一个在删除之前。无论何时触发触发器,它都会在表B上写一行,就像某种日志一样。 所有触发器都配置在xxx之前的“和每行的”上。使用单个查询,我可以看到它们正在工作 但是,当我在一个事务中对同一行进行两次查询修改时(通常,我修改一行,然后将其删除,从而执行update和delete),只运行第一个触发器(update)。在事务结束时,我可以看到表A中的我的行已被删除,但表B中只有一行显

我正在处理Oracle 10g DB,事务中的触发器有问题。
表A
有3个触发器:一个在插入之前,一个在更新之前,最后一个在删除之前。无论何时触发触发器,它都会在
表B
上写一行,就像某种日志一样。 所有触发器都配置在xxx之前的
“和每行的
”上。使用单个查询,我可以看到它们正在工作

但是,当我在一个事务中对同一行进行两次查询修改时(通常,我修改一行,然后将其删除,从而执行
update
delete
),只运行第一个触发器(
update
)。在事务结束时,我可以看到
表A
中的我的行已被删除,但
表B
中只有一行显示了更新操作,而不是删除操作


我可能误解了什么。这是来自触发器配置吗?

第二个触发器没有理由不触发,还有其他原因

下面是一个小测试用例,它显示了当一个事务多次修改一行时,所有触发器都会正确触发:

SQL> CREATE TABLE a (ID NUMBER);

Table created

SQL> CREATE TABLE b (action VARCHAR2(3), id_old NUMBER, id_new NUMBER);

Table created

SQL> CREATE TRIGGER trg_a_ins BEFORE INSERT ON a FOR EACH ROW
  2  BEGIN
  3     INSERT INTO b VALUES ('ins', :old.id, :new.id);
  4  END;
  5  /

Trigger created

SQL> CREATE TRIGGER trg_a_upd BEFORE UPDATE ON a FOR EACH ROW
  2  BEGIN
  3     INSERT INTO b VALUES ('upd', :old.id, :new.id);
  4  END;
  5  /

Trigger created

SQL> CREATE TRIGGER trg_a_del BEFORE DELETE ON a FOR EACH ROW
  2  BEGIN
  3     INSERT INTO b VALUES ('del', :old.id, :new.id);
  4  END;
  5  /

Trigger created

SQL> INSERT INTO a VALUES (1);

1 row inserted

SQL> UPDATE a SET ID = 2 WHERE ID = 1;

1 row updated

SQL> DELETE FROM a WHERE ID = 2;

1 row deleted

SQL> select * from b;

ACTION     ID_OLD     ID_NEW
------ ---------- ----------
ins                        1
upd             1          2
del             2 

正如@Vincent Malgrat所说,还有一些事情正在发生。表B是否有一个带有唯一索引的日期列?想到的第一种可能性是,插入的两个记录具有相同的日期(审计)值,精确到最接近的第二个;索引冲突导致删除操作的第二次插入出错;但这在delete触发器中被压缩了。我知道这是一种推测,使用时间戳列的可能性较小,如果时间正好,偶尔也会像预期的那样工作。

一个ORM可以(也是可取的)将多个更改“压缩”到一个记录中。因此,代码可能会更新三个属性,ORM可能在其缓存中多次更新记录/实例,但在事务结束时只发送一条update语句。或者,如果记录最终被删除,它可能会跳过任何更新,只删除原始记录


也就是说,我无法解释为什么可以在不触发DELETE触发器的情况下删除记录。我假设您使用的是真正的删除,而不是“软”删除(它将记录标记为已删除,只是将其隐藏在视图中)。

感谢您的测试用例。结构图与我们的很接近(当然更复杂)。我试过了,它成功了。事实上,还有一点,表B没有日期列(尽管计划在不久的将来进行,并且不会编制索引)。相反,我在表B上有一个主键,它的值是使用表B上的触发器从序列中获取的(在插入之前,针对每一行)。它可能来自第二个触发器吗?另一个信息:我正在使用Hibernate访问数据库(插入、更新、删除)。我知道,当Oracle触发来自触发器的错误时,我的java代码中有一个异常。不过,在本例中,我没有看到来自Oracle的异常。其中一个触发器可能是挤压异常,这样Hibernate就没有机会看到它,但这只是一个猜测。向问题中添加表结构和触发器代码可能会有所帮助。