觸發器:在執行insert,updatedalete語句時,
觸發執行的一段plsql代碼sql
能夠在sql語句執行前觸發,也能夠在sql語句執行後觸發,
還能夠替換原sql語句只執行觸發器代碼數據庫
讓觸發器失效
alter trigger 觸發器名 disable;
oracle
讓觸發器生效
alter trigger 觸發器名 enable;
測試
刪除觸發器
drop trigger 觸發器名;
日誌
表級觸發器:一個sql語句只會觸發一次觸發器代碼code
語法rem
create trigger 觸發器名稱 before|alter insert[or delete[or update]] on 表名 begin end;
給emp建立一個觸發器,當給emp表插入數據時,打印'插入數據'
新建t1觸發器it
create trigger t1 before insert on emp begin dbms_output.put_line('插入數據'); end;
插入數據進行測試io
insert into emp(empno,ename,deptno) values(7123,'asd',10); rollback;
會輸出table
插入數據
嘗試插入多條數據
insert into emp(empno,ename,deptno) select 1234,'a',10 from dual union all select 2345,'b',10 from dual union all select 3456,'c',10 from dual; rollback;
輸出
插入數據
發現插入多條數據時,也是打印了一次
觸發器中的三個變量,用來區分insert,update,delete語句的
變量名稱 | 描述 |
---|---|
inserting: | 布爾類型的變量,當insert語句觸發觸發器時,返回true,不然返回false |
updating: | 布爾類型變量,當update語句觸發觸發器時,返回true,不然返回false |
deleting: | 布爾類型變量,當delete語句觸發觸發器時,返回true,不然返回false |
新建觸發器
create or replace trigger t1 before insert or update or delete on emp begin if inserting then dbms_output.put_line('插入數據'); end if; if updating then dbms_output.put_line('修改數據'); end if; if deleting then dbms_output.put_line('刪除數據'); end if; end;
輸入
update emp set ename='slzd' where empno=7777;
輸出
修改數據
輸入
delete emp where empno in (9123,7777);
輸出
刪除數據
行觸發器:當表中一條數據改變時,觸發一次觸發器代碼
語法
語法
create or replace trigger 觸發器名 after|before insert [or update [or delete]] on 表名 for each row declare begin end;
建立觸發器
create or replace trigger t1 before insert or update or delete on emp for each row begin if inserting then dbms_output.put_line('插入數據'); end if; if updating then dbms_output.put_line('插入數據'); end if; if deleting then dbms_output.put_line('刪除數據'); end if; end;
插入一條數據
insert into emp(empno,ename,deptno) values(7123,'a',10);
輸出
插入數據
插入多條數據
insert into emp(empno,ename,deptno) select 7123,'a',10 from dual union all select 7124,'b',10 from dual union all select 7125,'c',10 from dual;
輸出
插入數據 插入數據 插入數據
刪除多條數據
delete from emp where empno in (1011,9123);
輸出
刪除數據 刪除數據
:old
獲取到數據當前記錄,修改以前的數據:new
獲取修改後(即將要修改)的數據create or replace trigger t1 before update on dept for each row begin --打印修改前的數據 dbms_output.put_line(:old.deptno||' , '||:old.dname||' , '||:old.loc); --打印修改後的數據 dbms_output.put_line(:new.deptno||' , '||:new.dname||' , '||:new.loc); end;
修改一條記錄
update dept set dname='aa',loc='bb' where deptno=10;
輸出
10 , ACCOUNTING , NEW YORK 10 , aa , bb
before
在sql語句執行後觸發after
在sql語句執行後觸發create or replace trigger t3 before update on dept for each row begin --打印修改前的數據 dbms_output.put_line(:old.deptno||' , '||:old.dname||' , '||:old.loc); --嘗試對:new進行賦值 :new.dname:='a'; :new.loc:='b'; --打印修改後的數據 dbms_output.put_line(:new.deptno||' , '||:new.dname||' , '||:new.loc); end;
修改一條記錄
update dept set dname='aa',loc='bb' where deptno=10;
輸出
10 , ACCOUNTING , NEW YORK 10 , a , b
發如今上面的例子中
使用before可以修改new的值
使用after時,不能修改new的值
新建日誌表
create table dept_log( dt date,--數據的修改時間 opt varchar2(20), --操做(insert,update,delete) old varchar2(100), --修改以前,源數據庫的數據 new varchar2(100) --修改以後,數據庫中的數據 );
爲dept表建立一個觸發器,記錄dept表的修改日誌
create or replace trigger log1 before insert or update or delete on dept for each row declare --聲明一個變量保存操做 v_opt varchar2(20); --聲明一個變量保存修改前的數據 v_old varchar2(100); --聲明一個變量保存修改後的數據 v_new varchar2(100); begin if inserting then v_opt:='insert'; v_old:=null; v_new:=:new.deptno||' , '||:new.dname||' , '||:new.loc; end if; if updating then v_opt:='update'; v_old:=:old.deptno||' , '||:old.dname||' , '||:old.loc; v_new:=:new.deptno||' , '||:new.dname||' , '||:new.loc; end if; if deleting then v_opt:='delete'; v_old:=:old.deptno||' , '||:old.dname||' , '||:old.loc; v_new:=null; end if; insert into dept_log(dt,opt,old,new) values(sysdate,v_opt,v_old,v_new); end;
測試
SQL> insert into dept values(50,'a','b'); 1 row inserted
SQL> update dept set dname='aa',loc='bb' where deptno=50; 1 row updated
SQL> delete from dept where deptno=50; 1 row deleted
查看dept_log表
SQL> select * from dept_log; DT OPT OLD NEW ----------- --------- -------------------- ----------- 2019/12/26 insert 50 , a , b 2019/12/26 update 50 , a , b 50 , aa , bb 2019/12/26 delete 50 , aa , bb
建立一個序列
create sequence seq111 start with 41 increment by 1;
建立一個觸發器給dept表自動添加主鍵
create or replace trigger t4 before insert on dept for each row begin :new.deptno:=seq111.nextval; end;
測試
insert into dept(dname,loc) values('aaa','ccc'); insert into dept(dname,loc) values('aaa','ccc'); insert into dept(dname,loc) values('aaa','ccc'); insert into dept(dname,loc) values('aaa','ccc'); commit;
查看dept表
SQL> select * from dept; DEPTNO DNAME LOC ------ -------------- ------------- 41 aaa ccc 42 aaa ccc 43 aaa ccc 44 aaa ccc 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 8 rows selected
注意若是執行插入語句報錯,會致使序列空一個數:41,43,44
刪除重複數據
delete from dept where deptno between 42 and 44;
若是不少條,重複數據,該如何刪除呢
delete from dept t where rowid> (select min(rowid) from dept where dname=t.dname and loc=t.loc);