如果在更新触发之前未在 oracle 中进行更新,则新值与旧值相同

Posted

技术标签:

【中文标题】如果在更新触发之前未在 oracle 中进行更新,则新值与旧值相同【英文标题】:New value is same as old value if not passed for update in oracle before update trigger 【发布时间】:2016-07-14 05:09:29 【问题描述】:

我创建了一个插入/更新前触发器,如下所示

CREATE OR REPLACE TRIGGER "AUDIT_TABLE_TRIG" BEFORE
  INSERT OR UPDATE ON AUDIT_TABLE FOR EACH ROW BEGIN :NEW.LAST_MODIFIED_DATE:=SYSDATE;
  IF :new.LAST_MODIFIED_BY = NULL THEN
    :NEW.LAST_MODIFIED_BY :=SYS_CONTEXT('USERENV','OS_USER');
  END IF;
END;

要求更新 last_modified_by 值与登录用户而不是操作系统用户相同,如果 last_modified_by 为空,则获取操作系统用户 ID。当我从 UI 更新此表时,它工作正常。最后按值修改的值是以登录用户 ID 的形式出现的(因为它是在更新语句中传递的)。 但是当我从 sql developer 更新 AUDIT_TABLE 中的其他列时, :new.last_modified_by 永远不会出现 null 而是它的值与 :old.last_modified_by 相同时间> Que1- 我处理这种情况的方式不如

 IF :new.LAST_MODIFIED_BY = NULL || :OLD.LAST_MODIFIED_BY !=SYS_CONTEXT('USERENV','OS_USER') THEN
            :NEW.LAST_MODIFIED_BY :=SYS_CONTEXT('USERENV','OS_USER');
 END IF;

还有其他好的方法可以解决这个问题吗? 问题2: 我遇到了这种情况,我感到很惊讶。如果新变量在更新时未更改,则新变量具有旧值是 oracle 触发器的标准行为吗?

【问题讨论】:

new variables have old values if they are not changed while updating ...如果旧值和新值相同,那么这不就是您在逻辑上所期望的吗? 如果我没有更改列值,我期待 :new .column 为空,因为它不在上下文中,或者我没有将任何东西作为新值传递..但看起来我错过了这个写触发器时。 :new.LAST_MODIFIED_BY = NULL 可能不会产生想要的结果,所以正确的写法是:new.LAST_MODIFIED_BY is NULL。根据我过去的经验,与val is NULL(或val is NOT NULL)相比,val = NULL 的可靠性较低。 感谢安贾恩。我会这样做的。 不相关,但是:您知道OS_USER 是客户端应用程序 提供的信息。我可以使用Krishnat Molawade 作为操作系统用户名连接到任何Oracle 服务器。不要依赖它! 【参考方案1】:

尝试使用 UPDATING 谓词,这可能会满足您的要求。

CREATE OR REPLACE TRIGGER "AUDIT_TABLE_TRIG" BEFORE
  INSERT OR UPDATE ON AUDIT_TABLE FOR EACH ROW BEGIN :NEW.LAST_MODIFIED_DATE:=SYSDATE;
  IF NOT UPDATING('LAST_MODIFIED_BY') THEN
    :NEW.LAST_MODIFIED_BY :=SYS_CONTEXT('USERENV','OS_USER');
  END IF;
END;

【讨论】:

我也需要空条件,因此将其处理为 IF NOT UPDATING('LAST_MODIFIED_BY') OR :NEW.LAST_MODIFIED_BY 为空 THEN :NEW.LAST_MODIFIED_BY :=SYS_CONTEXT('USERENV','OS_USER' );如果结束;

以上是关于如果在更新触发之前未在 oracle 中进行更新,则新值与旧值相同的主要内容,如果未能解决你的问题,请参考以下文章

使用 :new 和 :old 在更新和插入之前触发 Oracle

在更新触发器之前或之后更改同一表中的值(oracle)

Oracle - 触发器以在更新时创建历史记录行

在更新触发之前执行时出现约束冲突错误

更新之前的Oracle SQL触发器,用于设置来自其他实体的列值

使用触发器中断 Oracle 数据库删除和更新行