2012-03-17 58 views

回答

4

我假定你的意思是你有一個行級觸發器,而不是一個模式級觸發器。例如,某人在架構中的某個表上執行DDL時會觸發模式級別的觸發器。當您談論架構級觸發器時,談論新舊值是毫無意義的。

如果我們在談論行級觸發器,我假設您只對UPDATE報表感興趣。如果你插入或刪除數據,你自然會改變表中的每一列。

因此,如果我們正在討論在UPDATE上觸發的行級觸發器,則可以使用UPDATING函數。這會告訴你某個特定列是否正在更新。然而,它並不一定告訴你數據正在改變。聲明

UPDATE table_name 
    SET col1 = col1; 

更新COL1的每一行中TABLE_NAME,但實際上並沒有改變任何數據。如果這是可以接受的,你可以這樣做

CREATE TRIGGER trg_table_name 
    BEFORE UPDATE ON table_name 
    FOR EACH ROW 
BEGIN 
    IF(updating('COL1')) 
    THEN 
    <<col1 was updated>> 
    END IF; 

    IF(updating('COL2')) 
    THEN 
    <<col2 was updated>> 
    END IF; 

    ... 
END; 

你可以做的是更加動態的只是在循環中的數據USER_TAB_COLS,即

SQL> ed 
Wrote file afiedt.buf 

    1 create table foo (
    2 col1 number, 
    3 col2 number, 
    4 col3 number 
    5*) 
SQL>/

Table created. 

SQL> create trigger trg_foo 
    2 before update on foo 
    3 for each row 
    4 begin 
    5 for cols in (select * 
    6     from user_tab_cols 
    7     where table_name = 'FOO') 
    8 loop 
    9  if updating(cols.column_name) 
10  then 
11  dbms_output.put_line('Updated ' || cols.column_name); 
12  end if; 
13 end loop; 
14 end; 
15/

Trigger created. 

SQL> set serveroutput on; 
SQL> insert into foo values(1, 2, 3); 

1 row created. 

SQL> update foo 
    2  set col2 = col2 + 1, 
    3   col3 = col3 * 2; 
Updated COL2 
Updated COL3 

1 row updated. 

雖然這可以告訴你所有正在更新的列,但是,主要的缺點是,有沒有辦法訪問類似的時尚動感的:new:old值。因此,您可以發現COL2已更新,但您無法確定:new.col2:old.col2值是不是靜態引用這些值。

根據您要解決的問題,您可以通過查看數據字典中的數據來編寫動態生成觸發器的代碼。沿着這個塊的東西線會產生打印出所有的:new

DECLARE 
    l_tbl_name VARCHAR2(100) := 'FOO'; 
    l_sql_stmt VARCHAR2(4000); 
BEGIN 
    l_sql_stmt := 'CREATE OR REPLACE TRIGGER trg_' || l_tbl_name || 
       ' BEFORE UPDATE ON ' || l_tbl_name || 
       ' FOR EACH ROW ' || 
       'BEGIN '; 
    FOR cols IN (SELECT * 
       FROM user_tab_cols 
       WHERE table_name = l_tbl_name) 
    LOOP 
    l_sql_stmt := l_sql_stmt || 
        ' IF UPDATING(''' || cols.column_name || ''') ' || 
        ' THEN ' || 
        ' dbms_output.put_line(:new.' || cols.column_name || '); ' || 
        ' END IF; '; 
    END LOOP; 
    l_sql_stmt := l_sql_stmt || ' END; '; 
    dbms_output.put_line(l_sql_stmt); 
    EXECUTE IMMEDIATE l_sql_stmt; 
END; 
+0

謝謝!而已!, – destiny 2012-03-19 09:56:32

2
  :old   :new 
======================================================= 
insert | null   | new value to be inserted 
update | old value | new value to be updated 
delete | old value | null 
======================================================= 

上述值是參考稱爲行級觸發器,這意味着被觸發的每一行每次燒製。

上面的表格顯示了關於上述dml語句的新舊值,我們舉個例子。

Insert into abc (1,'gaurav soni',pune);--empid,name,city 

假設我有表ABC一個觸發器,它插入到表ABC時,檢查城市是否出現在位置表或不(我知道我們可以用外鍵約束做到這一點),但是這是一個例子,所以我們可以參考:new.city這個城市,但是因爲它的值是null,所以在插入的情況下我們不能指:old .city

update情況下,我們可以參考兩個:new and :old value

delete大家可以參考情況下,只有old value作爲new value是在deleting情況null

注意:在inserting情況下的delete:old情況下使用的:new不會給你compile time error,但肯定會繁榮,給你run time error 您可以使用INSERTING,DELETING子句來避免這種情況。

+0

謝謝某特定表的觸發器,但我比較每列的唯一途徑?我搜索了一個函數,它給了我更改的列 – destiny 2012-03-17 23:11:50

+0

@destiny:我沒有得到你要找的東西,請詳細說明你的答案,可能是賈斯汀幫助你的答案,但他也是假設,請詳細說明其他人可能會明白你在找什麼。 – 2012-03-18 04:54:56