如果在更新触发之前未在 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