2009-09-14 113 views
9

在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; 

現在我要做到以下幾點:我不t想要觸發器觸發,當只有一個列被更新。這怎麼可能?

我可以列出除了那個之外的所有列,這些列不應觸發觸發器。對於有許多列的表格,這非常麻煩。

另一種方法是使用更新功能是這樣的:

if not updating('COL3') then ... 

但如果我一旦改變COL1 COL3的,語句的計算結果爲假。這不是我想要的,因爲我想限制執行時只有一個列(COL3)已更新。

+0

使用數據字典列出所有列不那麼麻煩。 'SELECT column_name FROM user_tab_columns WHERE table_name ='MY_TABLE'AND column_name!='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; 

也許並不十分有效,但!

0

我不認爲有一種方法可以避免必須列出表格中的所有其他列,無論是在觸發器主體中還是在before update of ...子句中。

但是,如果添加或刪除任何列,您可能可以在表上編寫alter trigger來自動重新生成更新觸發器。這是一個更多的工作,但維護應該是自動的。

3

這可能不是你想要聽到的答案,但我認爲你過分誇大了維護的負擔。桌子結構在投入生產後經常變換是不正常的。如果你確實有一個表格,這個表格可能會頻繁更改列號或名稱,那麼我建議你有一個更大的架構問題。

因此,現在只需輸入所有列名稱,然後等待maintanance是否成爲問題。在觸發器中編寫一個複雜的實現是不值得的 - 您將在每次更新時支付一筆稅費 - 以避免偶爾更改DDL腳本。

5

昨天我有同樣的問題。 我想編寫一個觸發器,在除了一個字段的每個字段上觸發,表中有103個字段。

首先,我編碼:

if (:OLD.col1<>:NEW.col1 or :OLD.col2<>:NEW.col2 or :OLD.col3<>:NEW.col3 ....) 

但我有一些問題,空值,所以我說:

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 

這不是「優雅」,但...它工作完美。

+0

這實際上是所有最優雅的.. –