在oracle中我可以指定列,这应该会触发一个触发器:
create or replace trigger my_trigger
before update of col1, col2, col3 on my_table for each row
begin
// the trigger code will be executed only if col1 or col2 or col3 was updated
end;
现在我想执行以下操作:当仅更新一个列时,我不希望触发器触发。这怎么可能?
我可以列出除了那个之外的所有列,这些列不应该触发触发器。对于包含许多列的表来说,这非常麻烦。
另一种方法是使用UPDATING函数,如下所示:
if not updating('COL3') then ...
但如果我立刻更改了COL1 和 COL3,则语句的计算结果为false。这不是我想要的,因为我想在只有一个列(COL3)更新时限制执行。
答案 0 :(得分:11)
你可以这样做:
create or replace trigger my_trigger
before update on my_table
for each row
declare
n_cols integer := 0;
begin
for r in (select column_name from all_tab_columns
where table_name = 'MY_TABLE'
and owner = 'MY_SCHEMA')
loop
if updating(r.column_name) then
n_cols := n_cols + 1;
exit when n_cols > 1;
end if;
end loop;
if n_cols > 1 then
do_something;
end if;
end;
虽然可能效率不高!
答案 1 :(得分:5)
昨天我遇到了同样的问题。 我想编写一个触发器,除了一个字段外,每个字段都触发一个触发器,该表有103个列。
首先我编码:
if (:OLD.col1<>:NEW.col1 or :OLD.col2<>:NEW.col2 or :OLD.col3<>:NEW.col3 ....)
但是我对null值有一些问题,所以我补充说:
if (NVL(:OLD.col1,0)<>NVL(:NEW.col1,0) or NVL(:OLD.col2,0)<>NVL(:NEW.col2,0) ....)
但是后来我在DATE列中遇到了一些问题,它变得一团糟......
我认为最好的解决方案是列出要在“OF”中验证的所有列:
AFTER INSERT OR UPDATE of cOL1, col2, col3 ... colN ON table1
这不是“优雅”,但......它运作得很完美。
答案 2 :(得分:3)
这可能不是你想听到的答案,但我认为你过分夸大了维护的负担。表格结构在投入生产后经常变化是不正常的。如果您的表格经常更改列号或名称,那么我建议您有更大的架构问题。
因此,现在只需键入所有列名称,然后等待维护成为问题。当然不值得在触发器中编写复杂的实现 - 您将在每次更新时支付的税 - 以避免偶尔更改DDL脚本。
答案 3 :(得分:0)
我认为有一种方法可以避免必须列出表中的所有其他列,无论是在触发器主体中还是在before update of ...
子句中。
但是,您可以在表上编写alter trigger,以便在添加或删除任何列时自动重新生成更新触发器。这是一个更多的工作,但然后维护应该是自动的。