oracle觸發器

oracle觸發器

觸發器:在執行insert,updatedalete語句時,
觸發執行的一段plsql代碼sql

能夠在sql語句執行前觸發,也能夠在sql語句執行後觸發,
還能夠替換原sql語句只執行觸發器代碼數據庫

觸發器管理

讓觸發器失效
alter trigger 觸發器名 disable;oracle

讓觸發器生效
alter trigger 觸發器名 enable;測試

刪除觸發器
drop trigger 觸發器名;日誌

1表級觸發器(語句級觸發器)

表級觸發器:一個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);

輸出

刪除數據

2行級觸發器

行觸發器:當表中一條數據改變時,觸發一次觸發器代碼
語法

語法

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和after區別

  • 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的值

爲dept表實現日誌記錄

新建日誌表

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);
相關文章
相關標籤/搜索