Oracle 原理:DML触发器和数据库触发器
一、DML觸發(fā)器
觸發(fā)器的作用即當(dāng)某個(gè)事件發(fā)生時(shí)會(huì)自動(dòng)執(zhí)行執(zhí)行程序段里的內(nèi)容。
觸發(fā)器可以作用于表或者視圖,可以指定在insert 或update 或delete? 操作前、操作時(shí)、操作后 執(zhí)行特定的程序段。
CREATE [OR REPLACE] TRIGGER triggername BEFORE/INSTEAD OF/AFTER ---選擇事件觸發(fā)(前,時(shí),后)執(zhí)行 PL/SQL代碼塊[INSERT [OR] UPDATE [OR] DELETE] ---當(dāng)執(zhí)行 插入 、更新、刪除前觸發(fā)ON tblname_or_viewname ---確認(rèn)作用的表或者視圖[Referencing {OLD [AS] old / NEW [AS] new }] [FOR EACH ROW] --指定行級觸發(fā)器,不指定就是表級觸發(fā)器[WHEN (condition)] --當(dāng)符合condition的條件滿足時(shí)觸發(fā) DECLARE-- local variables here BEGIN;--PL/SQL blockEND triggername ;在sqlserver 中 Deleted 是一張臨時(shí)表存即將被更新刪除的老信息,對應(yīng)Oracle 中的 :old? ,Inserted 是一張臨時(shí)表用來存即將插入更新的新信息,對應(yīng)Oracle 中的 :new。 :new 和:old 表示即將操作的一行數(shù)據(jù)而不是代表整個(gè)數(shù)據(jù)集,所以,在用這兩個(gè)的時(shí)候通常要加上[FOR EACH ROW] 來指明行觸發(fā)器。 其中 對于update的操作實(shí)際上是先把數(shù)據(jù)放入:old再刪除再把新數(shù)據(jù)放入:new插入到數(shù)據(jù)庫中。
由于:old是存的是老數(shù)據(jù)是即將被刪除或更改的,所以更新old沒意義。after 已經(jīng)完成的操作后再觸發(fā),所以此時(shí)對新數(shù)據(jù)new進(jìn)行操作是無意義的。當(dāng)為after時(shí),無法修改? ? ?:new的記錄。
對于多表視圖,是可以改變鍵保留表中的內(nèi)容的。也可以對單表視圖j進(jìn)行DML操作
表級觸發(fā)器在當(dāng)對表或視圖事件觸發(fā)時(shí),只執(zhí)行1次。而行級觸發(fā)器在對表或視圖事件觸發(fā)時(shí),每影響1行數(shù)據(jù)就會(huì)執(zhí)行1次程序塊內(nèi)容
在DML觸發(fā)器中 不能使用rollback ,commit 還有DDL語句。
新建練習(xí)表 department_tbl:
新建如下觸發(fā)器,比較效果
create view VW_department_tbl as select * from department_tbl; --------insert視圖VW_department_tbl時(shí),給每行數(shù)據(jù)Leaders 默認(rèn)值'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時(shí),給每行數(shù)據(jù)Leaders 默認(rèn)值'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;對觸發(fā)器2執(zhí)行
對觸發(fā)器1執(zhí)行
新建觸發(fā)器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; --取不到還未提交的數(shù)據(jù) commit; end dep_insert; / create or replace trigger departInsertDefault3after insert --after 無法修改基表的數(shù)據(jù),需要自主事物處理的存儲過程配合,且新數(shù)據(jù)屬于未提交狀態(tài)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; --無法執(zhí)行dep_insert( :new.department,:new.all_salary);end departInsertDefault3 ; drop trigger departInsertDefault3;執(zhí)行
總之,如果要修改數(shù)據(jù)建議用 before? ,after適用于數(shù)據(jù)校驗(yàn),而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;最后執(zhí)行結(jié)果:
二、模式(DDL)觸發(fā)器
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 | 用于返回當(dāng)前數(shù)據(jù)庫名 |
| ora_des_encrypted_password | 用于返回DES加密后的用戶口令 |
| ora_dict_obj_name | 用于返回DDL操作所對應(yīng)的數(shù)據(jù)庫對象名 |
| ora_dict_obj_name_list(name_list_ OUT ora_name_list_t) | 用于返回字事件中被修改的對象名列表 |
| ora_dict_obj_owner | 用于返回DDL操作所對應(yīng)的對象的所有者名。 |
| ora_dict_obj_ower_list(ower_list OUT ora_name_list_t) | 用于返回在事件中被修改對象的所有者列表 |
| ora_dict_obj_type | 用于返回DDL操作所對應(yīng)的數(shù)據(jù)庫對象的類型。 |
| ora_grantee(user_list OUT ora_name_list_t) | 用于返回授權(quán)時(shí)事件授權(quán)者。 |
| 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錯(cuò)誤。 |
| ora_login_user | 用于返回登錄用戶名 |
| ora_sysevent? | 用于返回觸發(fā) 觸發(fā)器的系統(tǒng)時(shí)間名。 |
?
?
三、數(shù)據(jù)庫級觸發(fā)器
?
----數(shù)據(jù)庫啟動(dòng)觸發(fā)器----- create or replace trigger db_trigger after startup on database begin insert into obj_tbl values( ora_sysevent,null,SYSDATE); end; / ----數(shù)據(jù)庫用戶登錄觸發(fā)器----- 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; /四、對觸發(fā)器的操作
alter tigger? ? tiggername? ?ENABLE/DISABLE? ? 打開關(guān)閉觸發(fā)器?
select * from dba_triggers/user_triggers? ?查詢觸發(fā)器信息
總結(jié)
以上是生活随笔為你收集整理的Oracle 原理:DML触发器和数据库触发器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle 原理: 集合数组,集合属性
- 下一篇: Oracle 原理:数据装载 ,SQLl