oracle pl/sql之觸發器(trigger)

一.oracle觸發器介紹sql

觸發器在數據庫裏以獨立的對象存儲,它與存儲過程和函數不一樣的是,存儲過程與函數須要用戶顯示調用才執行,而觸發器是由一個事件來啓動運行。即觸發器是當某個事件發生時自動地隱式運行。而且,觸發器不能接收參數。因此運行觸發器就叫觸發或點火(firing)。ORACLE事件指的是對數據庫的表進行的INSERT、UPDATE及DELETE操做或對視圖進行相似的操做。ORACLE將觸發器的功能擴展到了觸發ORACLE,如數據庫的啓動與關閉等。因此觸發器經常使用來完成由數據庫的完整性約束難以完成的複雜業務規則的約束,或用來監視對數據庫的各類操做,實現審計的功能。數據庫

二.觸發器語法安全

觸發器由觸發事件,觸發條件和觸發操做三部分組成。oracle

(1)觸發事件app

指引發觸發器被觸發的SQL語句,數據庫事件或者用戶事件。ide

具體觸發事件:函數

啓動和關閉數據庫實例spa

oracle錯誤消息對象

用戶登陸和斷開會話事件

特定表和視圖的DML操做

在任何方案上的DDL操做

(2)觸發條件(可選)

指使用when子句指定一個BOOLEAN表達式,當布爾表達式爲TRUE時,會自動執行觸發器相應代碼。

(3)觸發操做

指包含SQL語句和其餘執行代碼的PL/SQL塊。

限制條件:

1.觸發器代碼不能超過32K。

2.觸發器代碼中不能使用long or long raw數據類型。

###基於視圖的觸發器instead of觸發器

###DML觸發器包括語句觸發器和行觸發器

DML須要指定觸發時機(before|after),觸發事件(insert,update,delete),表名,觸發類型,觸發條件,觸發操做。

觸發時機:用於指定觸發器的觸發時間。before表示執行DML操做以前觸發觸發器。

觸發事件:用於指定致使觸發器執行DML操做。

表名:用於指定DML操做所對應的表。

觸發類型:用於指定當觸發事件發生以後,須要執行幾回觸發操做。

觸發條件:用於指定執行觸發器的條件,只有條件爲TRUE時纔會執行觸發器代碼。

觸發操做:用於指定觸發器執行代碼。

三.觸發器類型

1.語句觸發器

當審計DML操做,或者確保DML操做安全執行時,可使用語句觸發器。語句觸發器不能記錄列數據的變化。

語法:

create or replace trigger trigger_name

timing event1 [or event2 or event3]

on table_name

pl/sql block;

(1)before語句觸發器

//禁止工做人員在週一改變僱員信息

create or replace trigger tr_change_emp
before insert or update or delete
---insert update delete三種操做觸發觸發器
on emp
begin
if to_char(sysdate,'DY','nls_date_language=AMERICAN') IN ('MON') then
---自定義錯誤輸出
    raise_application_error(-20001,'You can not change employee infor.');
end if;
end;

當觸發器中同時包含多個觸發事件時(insert,update,delete).區分具體的觸發事件,可使用3個爲此:

inserting,updating,deleting

create or replace trigger tr_change_emp
before insert or update or delete
on emp
begin
  if to_char(sysdate, 'DY', 'nls_date_language=AMERICAN') IN ('MON') then
    case
    when inserting then
        raise_application_error(-20001, 'You can not insert employee infor.');
    when updating then
        raise_application_error(-20002, 'You can not update employee infor.');
    when deleting then
        raise_application_error(-20003, 'You can not delete employee infor.');
    end case;
end if;
end;

(2)after語句觸發器

//審計emp表上insert,update,delete操做次數

思路

1.首先建立一個統計表t_audit,用於統計針對emp表的insert,update,delete次數

2.統計表中的第一個字段names,能夠支持對多個表進行統計,每一個表爲一行,有insert次數,update次數,delete次數

3.添加if語句檢測,若是某個表是首次進行統計,則在統計表中新建一條記錄,並把此表的各項次數初始化爲0

---首先建立表
create table t_audit(names varchar2(30) not null primary key,insert_count number,update_count number,delete_count number,start_date date,end_date date);
---建立觸發器
create or replace trigger tr_audit_emp
after insert or update or delete on emp
---on emp代表針對emp表有效
declare
    v_tmp number;
begin
---
    select count(*) INTO v_tmp from t_audit where names = 'EMP';
if v_tmp = 0 then
    insert into t_audit values ('EMP', 0, 0, 0, sysdate, null);
end if;
case
when inserting then
    update t_audit set insert_count = insert_count + 1 where names = 'EMP';
when updating then
    update t_audit set update_count = update_count + 1 where names = 'EMP';
when deleting then
    update t_audit set delete_count = delete_count + 1 where names = 'EMP';
end case;
end;

2.行觸發器

行觸發器是指執行DML操做時,每做用一行就觸發一次的觸發器。審計數據變化時,可使用行觸發器。

語法:

create or replace trigger trigger_name

timing event1 [or event2 or event3]

on table_name

[reference OLD AS old|NEW AS new]

FOR EACH ROW

[when condition]

PL/SQL block;

reference:用於指定新,舊數據的方式。默認狀況下OLD修飾符引用舊數據,使用NEW修飾符引用新數據。

FOR EACH ROW:表示創建行觸發器

(1)before行觸發器

//確保僱員工資不低於其原有工資

create or replace trigger tr_update_sal
before update of sal on emp
for each row
begin
if :NEW.sal < :OLD.sal then
   raise_application_error(-20001,'salary up');
end if;
end;

(2)

//審計僱員工資的變化

--首先建立用於統計的表
CREATE TABLE "T_AUDIT_SALARY"
   ("ENAMES" VARCHAR2(50),
"OLDSAL" NUMBER(7,2),
"NEWSAL" NUMBER(7,2),
"CREATE_DATE" TIMESTAMP
   );
--建立觸發器,after後跟觸發事件
create or replace trigger tr_audit_salary
after update of sal on emp
for each row
--after update of sal on emp指定觸發的字段(sal),以及對此字段的操做(update)
declare
    v_tmp number;
begin
--if判斷用於新增一條統計信息,:old.ename爲emp表中僱員姓名,當首次更新emp表中某一位僱員姓名時,把此僱員姓名(:old.ename)做爲一行新增到統計表中
    select count(*) into v_tmp from t_audit_salary where enames=:old.ename;
if v_tmp =0 then
    insert into t_audit_salary values(:old.ename,:old.sal,:new.sal,sysdate);
else
    update t_audit_salary set oldsal=:old.sal,newsal=:new.sal,create_date =sysdate
where enames=:old.ename;
end  if;
end;

3.系統事件觸發器

系統事件觸發器指基於oracle系統事件所創建的觸發器,提供了跟蹤系統內或數據庫變化的機制。

常見的系統事件屬性函數:

ora_client_ip_address:用於返回客戶端的IP地址。

ora_database_name:用於返回當前數據庫名。

ora_login_user:用於返回登陸用戶名。

ora_sysevent:用於返回觸發觸發器的系統事件名。

//記錄用戶登陸和退出

首先建立記錄表

create table t_login(username varchar2(50),logon_date date,logoff_date date,address varchar2(15));

建立登錄數據庫事件觸發器

create or replace trigger tr_login
after logon on database
begin
    insert into t_login(username,logon_date,address)
values(ora_login_user,sysdate,ora_client_ip_address);
end;

建立退出數據庫觸發器

create or replace trigger tr_logoff
before logoff on database
--before操做說明是在退出數據庫以前觸發
begin
    insert into t_login(username,logoff_date)
values(ora_login_user,sysdate);
end;

//記錄數據庫啓動和關閉

--首先建立記錄表
create table t_sysevent(events varchar2(50),create_date timestamp);
--數據庫啓動觸發器
create or replace trigger tr_startup
after startup on database
begin
    insert into t_sysevent values(ora_sysevent,sysdate);
end;
--數據庫關閉觸發器
create or replace trigger tr_shutdown
before shutdown on database
begin
    insert into t_sysevent values(ora_sysevent,sysdate);
end;

四.管理觸發器

--查看做用與某張表上的全部觸發器

select TRIGGER_NAME,table_name,status from user_triggers where table_name='EMP';

---禁止某個觸發器

alter trigger trigger_name disable;

---啓用觸發器

alter trigger TR_STARTUP enable;

相關文章
相關標籤/搜索