【问题标题】:ON DELETE trigger - join on old valuesON DELETE 触发器 - 加入旧值
【发布时间】:2016-06-06 16:09:39
【问题描述】:

我尝试使用删除和更新触发器记录对 DB2 表的更改。 让我们假设一个简单的例子:一个人有一个地址。日志表不仅应包含人员数据,还应包含地址表中的一些值。

所以表格是 PERSON (ID, NAME) 和 ADDRESS(PERSON_ID, STREET, ...)

这是我尝试设置的:

CREATE TRIGGER log_history
AFTER UPDATE OR DELETE ON person
REFERENCING OLD AS O
FOR EACH ROW MODE DB2SQL
BEGIN
 DECLARE street VARCHAR(150);
 SET street = (SELECT street from ADDRESS join person on ADDRESS.person_id=O.id);
 INSERT INTO LOG(id,name,street) VALUES(O.id, O.name, street);
END

更新被完美记录。我看到所有旧值都插入到日志表中,包括街道。

对于 DELETE 操作,日志行仅包含 PERSON 表的值,但 STREET 列对于已删除的行为 NULL。

我还尝试使用 BEFORE 触发器,并尝试使用简单的 where 子句加入。结果总是一样的。

我可能应该提到,当您删除 PERSON 时,有一个 ON DELETE CASCADE FK 会删除 ADDRESS。但是,我的理解是删除该依赖表(地址 ) 发生在触发器之后...

我在 Linux 服务器上使用 DB2 10.5 LUW(应该不相关,但是...)

那么有人知道如何从另一个表中检索连接值而不是触发删除的表吗?谢谢

【问题讨论】:

  • 您的理解似乎不正确。 AFTER 触发器“在主题表的实际更新导致的更改应用于数据库之后”触发 - 来自the manual 的引用。注意“数据库”与“表”。这显然包括“由主题表的实际更新引起的”级联操作。
  • mustaccio,正如我所说,我还尝试了 BEFORE 触发器,结果相同。如果我理解正确,您建议尝试“在更新或删除之前不要级联”。我会尝试。我想我也尝试过,但在添加触发器时遇到了问题,其中包含我不太理解的消息。我会及时通知你我的结果。感谢您的评论
  • 似乎 NO CASCADE BEFORE 选项有效。现在我有另一个问题:我在我的程序中使用了一个聪明的持久性框架,它确定地址对象也需要被删除,所以如果我想使用 TRIGGER 解决方案,我必须用它来对抗框架缓存和对象映射之类的,这听起来像是一场你只能输的战斗。

标签: triggers db2 foreign-keys


【解决方案1】:

正如 mustaccio 所建议的,NO CASCADE BEFORE DELETE OR UPDATE 将允许我检索已删除行引用的连接值。 不幸的是,我无法遵循这条路线,因为我们使用的持久性框架“足够聪明”,可以在删除人员之前为地址表发出删除语句。 更改我们的 O/R 映射并为这种特殊的日志记录目的教给框架额外的技巧似乎是一项冒险的尝试。似乎在程序端实现日志记录行为是相当的努力和风险较小。所以我决定根本不使用 TRIGGER。

无论如何,感谢 mustaccio 的评论和指点。

【讨论】:

    【解决方案2】:

    只是为了完成这个线程: 以编程方式做事并没有真正奏效,因为那样我们就必须在应用程序端跟踪旧值。

    那么我们最终得到了什么?我们编写了一个存储过程,并在每次在当前(应用程序端)事务中更改相关记录时调用它。这有许多限制,最糟糕的(幸运的是,在我们的例子中是可以管理的)一个是您必须考虑手动调用该存储过程。桌上的触发器会更安全......哦,我的。

    【讨论】:

      猜你喜欢
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2011-09-21
      • 2014-09-26
      • 1970-01-01
      相关资源
      最近更新 更多