PL/SQL高級應(yīng)用 觸發(fā)器

之前所有創(chuàng)建的PL/SQL程序都是匿名的侥啤,沒有為程序塊提供一個名詞洲炊, 這就無法被存儲,每次只需后不可以被重復(fù)使用, 每次允許匿名塊的時候都需要先編譯踪栋,在執(zhí)行,在很多時候為了提高系統(tǒng)的應(yīng)用性能浴鸿,需要數(shù)據(jù)庫保存程序塊盈匾,方便以后重復(fù)使用,這就意味著程序塊需要一個名詞

命名程序塊: 過程虹脯, 函數(shù)驴娃, 程序包, 觸發(fā)器循集。唇敞。。

存儲過程

存儲過程是用于執(zhí)行特定操作
1. 創(chuàng)建
create [or replace] procedure procedure_name
[(paramater_name[in|out|in out] datatype[m],....])]

create or replace  procedure out_time
  is 
begin
  dbms_output.put_line('當前時間'||systimestamp);
  end;
drop procedure out_time;
  call out_time();
  1. 調(diào)用
    exec
    call

  2. 修改
    or replace

  3. 刪除
    drop
    參數(shù)
    create or replace procedure add_dept
    (dno number, dname varchar2 default null, loc varchar2 default null)
    is
    begin
    insert into dept values(dno, dname,loc);
    end;

--drop procedure add_dept;
--call add_dept(13,'吃飯餓啊'咒彤,'新鄉(xiāng)');

1. 位置傳值
按照定義參數(shù)的順序依次為參數(shù)指定響應(yīng)的變量和值
call add_dept(50,loc => '你好')
  select * from dept;
參數(shù)模式
  1. in: 輸入?yún)?shù)
  2. out: 輸出參數(shù)
  3. in out : 輸入輸入出函數(shù)
    create or replace procedure pro_result (num1 in out number, num2 in out number)
    is
    v_result number(6,3);
    v_reamin number(6);
    begin
    v_result := num1/num2;
    v_reamin := mod(num1,num2);
    num1 := v_result;
    num2 := v_reamin;
    end;
    --drop procedure pro_result
    declare
    v_n1 number := 8;
    v_n2 number := 3;
    begin
    pro_result(num1 => v_n1,num2 => v_n2);
    dbms_output.put_line(v_n1||' '||v_n2);
    end;
函數(shù) :
函數(shù)用于返回特定的數(shù)據(jù)疆柔,如果在應(yīng)用程序中進程需要通過SQL語句來返回特定數(shù)據(jù),可以創(chuàng)建函數(shù)和存儲過程镶柱,存儲過程

create or replace function get_name(eno number)
return varchar2
as
v_name emp.ename%type;
begin
select ename into v_name from emp where empno =eno;
return v_name;
end;

declare
str varchar2(30);
begin
str:= get_name(7788);
dbms_output.put_line('姓名: '||str);
end;

create or replace function get_workyear(hiredate in date)
return number
as
v_worlyear number := 0;
begin
v_worlyear := extract(year from sysdate) - extract(year from hiredate);
return v_worlyear;
end;

   select e.*, get_workyear(hiredate) workd from emp e; 

程序包

create or replace package pack_test
as
   v_temp number ;-- 定義全局
   procedure p1(x number);--定義存儲過程
   end;
   create or replace package body pack_test
   as
   
   procedure p1(x number)
     as
     begin
       v_temp :=x;
       dbms_output.put_line(v_temp);
       end;
       end;

       begin
       pack_test.p1(44);
       end;  
       
create or replace package pack_emp is
procedure add_employee(eno number, name varchar2, salary number, dno number);
end;

  create or replace package body pack_emp is
-- 私有函數(shù)只能在包體中訪問
   function validata_deptno(v_deptno number)
     return boolean
     is
     v_temp int;
     begin
       select count(deptno) into v_temp from dept where deptno = v_deptno;
       if v_temp >0 then
         return true;
       else
         return false;
       end if;
   end validata_deptno;

procedure add_employee(eno number, name varchar2, salary number, dno number)
is
begin
if validata_deptno(dno) then
  insert into emp(empno,ename,sal,deptno,hiredate) values(eno,name,salary,dno,sysdate);
  else
    raise_application_error(-20060,'部門不存在');
    end if;
    exception
      when dup_val_on_index then
        raise_application_error(-20430,'該員工已存在');
        end add_employee;
        end pack_emp;        
        begin
          pack_emp.add_employee(eno => 1002,name => '依戀',salary => 3400,dno => 20);
        end;
        select * from emp ;

create or replace package pack_overload
is
function get_sal(eno number) return number;
function get_sal(name varchar2) return number;

/*procedure del_employee(eno number);
procedure del_employee(name varchar2);*/

end;

create or replace package body pack_overload
is 
function get_sal(eno number) return number
is
v_sal emp.sal%type;
begin
    select sal into v_sal from emp where empno = eno;
    return v_sal;
    exception
      when no_data_found then
        raise_application_error(-2030,'該員工不存在');
end get_sal;
function get_sal(name varchar2) return number
is
v_sal emp.sal%type;
begin
    select sal into v_sal from emp where upper(ename) = upper(name);
    return v_sal;
    exception
      when no_data_found then
        raise_application_error(-2030,'該員工不存在');
end get_sal;
end pack_overload;

declare
v_sal number;
begin
v_sal:= pack_overload.get_sal('ALLEN');
dbms_output.put_line(v_sal);
end;
select * from emp;

包的構(gòu)造

在包中定義全局變量旷档,有些時候,會話中可能還需要初始化全局變量歇拆,可以通過包構(gòu)造初始化
當在會話內(nèi)第一次調(diào)用公共組件的時候鞋屈,會自動執(zhí)行其構(gòu)造過程

聲明: 在包體的最后 添加begin關(guān)鍵字范咨, 后面編寫構(gòu)造內(nèi)容

create or replace package pack_emptest is
minsal number(6,2);
maxsal number(6,2);
procedure update_sal(eno number, salary number);
end;

create or replace package body pack_emptest is
procedure update_sal(eno number, salary number)
  is
  begin
  dbms_output.put_line(minsal||'   '||maxsal);
  end update_sal;

  begin  
  select min(sal),max(sal) into minsal,maxsal from emp;
  dbms_output.put_line('構(gòu)造被執(zhí)行');
  end pack_emptest;

  begin
    pack_emptest.update_sal(7788,1);
end;

觸發(fā)器

觸發(fā)器(tigger)是一種特殊的類型的pl/sql塊, 觸發(fā)器類似于過程和函數(shù)谐区, 也具有聲明部分湖蜕,執(zhí)行部分, 異常部分宋列, 觸發(fā)器是在數(shù)據(jù)庫事件發(fā)生時被隱式觸發(fā)昭抒,而且觸發(fā)器不能接受參數(shù),不能像過程函數(shù)已有顯示調(diào)用

觸發(fā)器組成
觸發(fā)事件: 引起觸發(fā)器被觸發(fā)的事件炼杖,例如DML語句(insert灭返,update,delete)語句的時候?qū)Ρ砘蛞晥D進行數(shù)據(jù)操作的時候觸發(fā)坤邪, DDL事件(create熙含,alter, drop)艇纺,數(shù)據(jù)庫事件(啟動怎静,退出,異常錯誤)用戶事件(登錄黔衡,退出)
觸發(fā)的時間 :設(shè)置觸發(fā)事件發(fā)生之前(before)還是之后(after)
觸發(fā)對象: 包括 表蚓聘,視圖,模式盟劫,數(shù)據(jù)庫夜牡, 只有在指定的對象上發(fā)生了特定的時間,才會被觸發(fā)
觸發(fā)條件: 是一個邏輯表達式
觸發(fā)頻率 : 設(shè)置語句基本的觸發(fā)器還是行基本的觸發(fā)器

觸發(fā)器的類型
  1. DML觸發(fā)器
    dml 所包含的事件 侣签,insert塘装, update, delete DML語句觸發(fā)器可以為這些觸發(fā)事件創(chuàng)建影所, before(發(fā)生前)和after(發(fā)生后)觸發(fā)器蹦肴,DML觸發(fā)器可以在語句級別或行級別操作上唄觸發(fā)
    語句級別是對每一個SQL語句只觸發(fā)一次,行級別對SQL影響的表中的每一行觸發(fā)一次

  2. DDL觸發(fā)器
    create猴娩。alter阴幌。drop

  3. 系統(tǒng)觸發(fā)器
    login , logoff serverror 胀溺。startup裂七, shutdown

  4. 替代觸發(fā)器
    在對視圖進行dml操作的時候執(zhí)行的觸發(fā)器

       create or replace trigger emp_count
       after delete on emp
       declare 
         v_con integer;
           begin
           select count(1) into v_con from emp;
       dbms_output.put_line('現(xiàn)在還有'||v_con||'行');
       end;
    
         select * from emp;
    
       delete from emp where empno = 1002; 
    

  create or replace trigger tri_emp
    before insert or update or delete on emp2
  begin
  if to_char(sysdate,'DY') in('星期六','星期日') then
  case
  when INSERTING then
    raise_application_error(-20006,'不能在休息日添加員工信息');
  when UPDATING then
    raise_application_error(-20006,'不能在休息日修改員工信息');
  when DELETING then
    raise_application_error(-20006,'不能在休息日刪除員工信息');
  end case;
 end if;
 end;

 delete from emp2 where deptno =20;
 
 update emp2 set comm = 500 where empno = 7902;
 
 create table emp2 as select * from emp;
  select * from emp2

數(shù)據(jù)庫觸發(fā)器

create table event_table(
event varchar2(30),
  time date
)

create or replace tirgger tir_startup
  after startup on database
begin
insert into event_table values (ora_sysevent, sysdata);
end;

  create or replace tirgger tir_shutdown
    after shutdown on database
  begin
insert into event_table values (ora_sysevent, sysdata);
end;

create table log_table(
username varchar(20),
log_time data,
logoff_time date,
address varchar(20)
);

登錄觸發(fā)
  create ot replace trigger tir_login
after logon on database
begin
insert into log_table (username,log_time,address)
values(ora_login_user, sysdate,ora_client_ip_address)
end;

退出觸發(fā)
create ot replace trigger tir_logoff
after logoff on database
begin
insert into log_table (username,logoff_time ,address)
values(ora_login_user, sysdate,ora_client_ip_address)
end;


DDL 觸發(fā)器
create or replace trigger tir_ddl
after ddl on scott.schema
begin
...
insert into event_ddl values(ora_sysevent,ora_login_user,ora_obj_owner,ora_dirct_obj_type,sysdate);
end;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市仓坞,隨后出現(xiàn)的幾起案子背零,更是在濱河造成了極大的恐慌,老刑警劉巖无埃,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徙瓶,死亡現(xiàn)場離奇詭異毛雇,居然都是意外死亡,警方通過查閱死者的電腦和手機侦镇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門灵疮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人壳繁,你說我怎么就攤上這事震捣。” “怎么了闹炉?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵蒿赢,是天一觀的道長。 經(jīng)常有香客問我渣触,道長羡棵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任嗅钻,我火速辦了婚禮皂冰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘养篓。我一直安慰自己秃流,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布觉至。 她就那樣靜靜地躺著剔应,像睡著了一般睡腿。 火紅的嫁衣襯著肌膚如雪语御。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天席怪,我揣著相機與錄音应闯,去河邊找鬼。 笑死挂捻,一個胖子當著我的面吹牛碉纺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刻撒,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼骨田,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了声怔?” 一聲冷哼從身側(cè)響起态贤,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎醋火,沒想到半個月后悠汽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箱吕,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年柿冲,在試婚紗的時候發(fā)現(xiàn)自己被綠了茬高。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡假抄,死狀恐怖怎栽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宿饱,我是刑警寧澤婚瓜,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站刑棵,受9級特大地震影響巴刻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛉签,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一胡陪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碍舍,春花似錦柠座、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捧书,卻和暖如春吹泡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背经瓷。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工爆哑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舆吮。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓揭朝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親色冀。 傳聞我的和親對象是個殘疾皇子潭袱,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容