使用觸發器做到在一個表更新記錄時將更新前的記錄存入另一個表

第一個表

SQL> desc new_table;
 名稱                                      是否爲空? 類型
 ----------------------------------------- -------- ---------------

 ID                                                 NUMBER(38)
 NAME                                               VARCHAR2(20)

用來存儲信息的表

SQL> desc history_table;
 名稱                                      是否爲空? 類型
 ----------------------------------------- -------- ------------

 ID                                                 NUMBER(38)
 NAME                                               VARCHAR2(20)
我想要更新new_table的時候將更新前的數據存入到history_table;有下面兩種方法:


第一種方法

create or replace trigger tr_update_newtable
before update on new_table for each row
begin
  insert into history_table values(:old.id,:old.name);
end;
/

這種方式優點是比較簡單易讀,缺點是如果列特別多的話就比較頭疼。

第二種方法

使用自治事務(pragma autonomous_transaction)

create or replace trigger tr_update_newtable
before update on new_table for each row
declare
  pragma autonomous_transaction;
begin
	insert into history_table (select * from new_table where id =:old.id);
	dbms_output.put_line(:old.id);
  commit;
end tr_update_newtable;

優點是不用輸入每一列的值,缺點是如果你不提交的話(用commit),在這裏的new_table是沒有更新的。這個很容易讓人疑惑,因爲在命令行用select * from new_table你會發現已經更新了。在沒有提交時,更新後的數據存在緩存裏,在命令行裏用select,會從緩存裏調數據,而上面的程序裏的select會讀存在數據庫裏的原始表。

下面的commit是必須的,否則可能在下一次更新時出現錯誤

SQL> select * from new_table;

        ID NAME
---------- ----------------------------------------
        39 junjie

SQL> select * from history_table;

未選定行

SQL> update new_table set id=40;
39

已更新 1 行。

SQL> commit;

提交完成。

SQL> select * from new_table;

        ID NAME
---------- ----------------------------------------
        40 junjie

SQL> select * from history_table;

        ID NAME
---------- ----------------------------------------
        39 junjie

另外,自治事務中執行的操作是不能用rollback回滾回來的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章