在Oracle中编写行级触发器时,我知道您可以使用OLD
和NEW
伪记录来引用触发触发器的行的旧状态和新状态。
我知道在INSERT
触发器中OLD
不包含任何数据,但我不确定这会如何影响该触发器的WHEN
子句的评估。例如,如果我有以下触发器:
CREATE OR REPLACE TRIGGER mung_row
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
BEGIN
:NEW.foo = 'some val';
END;
我希望将此触发器修改为仅在foo以前为null时运行更新,但始终在插入上运行,我可以通过添加WHERE
子句来满足更改的更新部分:
CREATE OR REPLACE TRIGGER mung_row
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
WHEN (OLD.foo IS NULL)
BEGIN
:NEW.foo = 'some val';
END;
这是否会导致插入案例出现问题? OLD.foo将在INSERT
中评估什么?
我知道我可以拆分INSERT
和UPDATE
触发器,或者在触发器主体中使用INSERTING
/ UPDATING
/ DELETING
,但我而不是在激发这个问题的情况下。
答案 0 :(得分:10)
插入记录时,OLD
的每个字段都为NULL
,包括表格定义中标记为NOT NULL
的字段。
例如,假设您的表具有名为id
的不可为空的列:
CREATE TABLE some_table (
id NUMBER NOT NULL,
foo VARCHAR2(100)
)
将记录插入此表后,OLD.id
将为NULL
。但是,在此表中更新记录时,OLD.id
将不是NULL
。因为您只想在更新记录时更改:NEW.foo
,所以您只需检查OLD.id
是否具有非空值。
CREATE OR REPLACE TRIGGER mung_row
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
WHEN (OLD.id IS NOT NULL AND OLD.foo IS NULL)
BEGIN
:NEW.foo = 'some val';
END;