Oracle:排除一列的更新以触发触发器

时间:2009-09-14 13:46:16

标签: sql oracle plsql triggers

在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)更新时限制执行。

4 个答案:

答案 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,以便在添加或删除任何列时自动重新生成更新触发器。这是一个更多的工作,但然后维护应该是自动的。