Oracle 原理:DML触发器和数据库触发器
一、DML觸發器
觸發器的作用即當某個事件發生時會自動執行執行程序段里的內容。
觸發器可以作用于表或者視圖,可以指定在insert 或update 或delete? 操作前、操作時、操作后 執行特定的程序段。
CREATE [OR REPLACE] TRIGGER triggername BEFORE/INSTEAD OF/AFTER ---選擇事件觸發(前,時,后)執行 PL/SQL代碼塊[INSERT [OR] UPDATE [OR] DELETE] ---當執行 插入 、更新、刪除前觸發ON tblname_or_viewname ---確認作用的表或者視圖[Referencing {OLD [AS] old / NEW [AS] new }] [FOR EACH ROW] --指定行級觸發器,不指定就是表級觸發器[WHEN (condition)] --當符合condition的條件滿足時觸發 DECLARE-- local variables here BEGIN;--PL/SQL blockEND triggername ;在sqlserver 中 Deleted 是一張臨時表存即將被更新刪除的老信息,對應Oracle 中的 :old? ,Inserted 是一張臨時表用來存即將插入更新的新信息,對應Oracle 中的 :new。 :new 和:old 表示即將操作的一行數據而不是代表整個數據集,所以,在用這兩個的時候通常要加上[FOR EACH ROW] 來指明行觸發器。 其中 對于update的操作實際上是先把數據放入:old再刪除再把新數據放入:new插入到數據庫中。
由于:old是存的是老數據是即將被刪除或更改的,所以更新old沒意義。after 已經完成的操作后再觸發,所以此時對新數據new進行操作是無意義的。當為after時,無法修改? ? ?:new的記錄。
對于多表視圖,是可以改變鍵保留表中的內容的。也可以對單表視圖j進行DML操作
表級觸發器在當對表或視圖事件觸發時,只執行1次。而行級觸發器在對表或視圖事件觸發時,每影響1行數據就會執行1次程序塊內容
在DML觸發器中 不能使用rollback ,commit 還有DDL語句。
新建練習表 department_tbl:
新建如下觸發器,比較效果
create view VW_department_tbl as select * from department_tbl; --------insert視圖VW_department_tbl時,給每行數據Leaders 默認值'BOSS'---- create or replace trigger departInsertDefault2Instead of insert --替換原有的insert語句,且Instead Of 只能作用于視圖, WHEN不能用于 INSTEAD OFon VW_department_tblFOR EACH ROW declare beginif :new.leaders is null theninsert into department_tbl values(:new.department,:new.all_salary,'BOSS');else insert into department_tbl values(:new.department,:new.all_salary,:new.leaders);end if; end departInsertDefault2 ; drop trigger departInsertDefault2; ----------------------------------- --------insert表department_tbl時,給每行數據Leaders 默認值'BOSS'---- create or replace trigger departInsertDefault1before insert on department_tbl FOR EACH ROWWHEN (new.leaders is null )declarebegin :new.leaders :='BOSS'; end departInsertDefault1 ; drop trigger departInsertDefault1;對觸發器2執行
對觸發器1執行
新建觸發器3,
create or replace procedure dep_insert(dep in department_tbl.department%type ,sal in department_tbl.all_salary%type) is PRAGMA AUTONOMOUS_TRANSACTION; --自主事物處理 begininsert into department_tbl values(dep,sal,'BOSS');--update department_tbl set leaders='BOSS' where leaders is null and department = dep; --取不到還未提交的數據 commit; end dep_insert; / create or replace trigger departInsertDefault3after insert --after 無法修改基表的數據,需要自主事物處理的存儲過程配合,且新數據屬于未提交狀態on department_tblFOR EACH ROWWHEN (new.leaders is null)declarev_data department_tbl%rowtype; begin --update department_tbl set leaders='BOSS' where leaders is null and department = :new.department; --無法執行dep_insert( :new.department,:new.all_salary);end departInsertDefault3 ; drop trigger departInsertDefault3;執行
總之,如果要修改數據建議用 before? ,after適用于數據校驗,而Instead of只能作用于視圖。
update 示例:
create or replace trigger departInsertDefault4before update on department_tblFOR EACH ROWwhen (old.department = new.department) declare begin :new.all_salary := :new.all_salary+:old.all_salary; end departInsertDefault4 ; / --drop trigger departInsertDefault4;truncate table department_tbl; insert into department_tbl(department,all_salary) values('部門1',2000); insert into department_tbl(department,all_salary,leaders) values('部門1',2000,'BOSS'); insert into department_tbl(department,all_salary,leaders) values('部門2',3000,'雇傭者1'); update department_tbl set department = '部門999' where Leaders is not null; update department_tbl set Leaders = 'boss' where Leaders is not null; commit; select * from department_tbl;最后執行結果:
二、模式(DDL)觸發器
Create table obj_tbl( obj_name varchar2(30), obj_type varchar2(20), obj_date Date )create or replace trigger obj_trigger after Create --alter drop on SCHEMA BEGINinsert into obj_tbl values( ora_dict_obj_name,ora_dict_obj_type,SYSDATE); END; /| ora_client_ip_address | 用于返回客戶端的IP地址 |
| ora_database_name | 用于返回當前數據庫名 |
| ora_des_encrypted_password | 用于返回DES加密后的用戶口令 |
| ora_dict_obj_name | 用于返回DDL操作所對應的數據庫對象名 |
| ora_dict_obj_name_list(name_list_ OUT ora_name_list_t) | 用于返回字事件中被修改的對象名列表 |
| ora_dict_obj_owner | 用于返回DDL操作所對應的對象的所有者名。 |
| ora_dict_obj_ower_list(ower_list OUT ora_name_list_t) | 用于返回在事件中被修改對象的所有者列表 |
| ora_dict_obj_type | 用于返回DDL操作所對應的數據庫對象的類型。 |
| ora_grantee(user_list OUT ora_name_list_t) | 用于返回授權時事件授權者。 |
| ora_instance_num | 用于返回歷程號。 |
| ora_is_alter_column(column_name IN VARCHAR2) | 用于檢測特定列是否被修改 |
| ora_is_creating_nested_table | 用于檢測是否正在建立嵌套表 |
| ora_is_drop_column(column_name IN VARCHAR2) | 用于檢測特定列是否被刪除 |
| ora_is_servererror(error_number) | 用于檢測是否返回了特定Oracle錯誤。 |
| ora_login_user | 用于返回登錄用戶名 |
| ora_sysevent? | 用于返回觸發 觸發器的系統時間名。 |
?
?
三、數據庫級觸發器
?
----數據庫啟動觸發器----- create or replace trigger db_trigger after startup on database begin insert into obj_tbl values( ora_sysevent,null,SYSDATE); end; / ----數據庫用戶登錄觸發器----- create or replace trigger user_trigger after logon on database begin insert into obj_tbl values( ora_login_user,ora_client_ip_address,SYSDATE); end; /四、對觸發器的操作
alter tigger? ? tiggername? ?ENABLE/DISABLE? ? 打開關閉觸發器?
select * from dba_triggers/user_triggers? ?查詢觸發器信息
總結
以上是生活随笔為你收集整理的Oracle 原理:DML触发器和数据库触发器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle 原理: 集合数组,集合属性
- 下一篇: Oracle 原理:临时表空间的操作方式