Oracle-存储过程(procedure、function、package、tigger)
存儲(chǔ)過(guò)程
概念:
完成特定功能的SQL語(yǔ)句集合,經(jīng)過(guò)編譯存儲(chǔ)在數(shù)據(jù)庫(kù)中
編譯后sql語(yǔ)句,可以通過(guò)調(diào)用過(guò)程來(lái)實(shí)現(xiàn)功能,不需要重新寫(xiě)sql語(yǔ)句
優(yōu)點(diǎn):
模塊化程序編程
減少網(wǎng)絡(luò)流通量
提高安全性
執(zhí)行速度快
過(guò)程procedure
創(chuàng)建過(guò)程
create [ or replace ] procedure 過(guò)程名稱 [ ( 參數(shù)列表) ] { is | as }----聲明變量begin----執(zhí)行代碼end [過(guò)程名稱];例如:
create or replace procedure myprocasm number;beginm:=100;dbms_output.put_line(m);end;調(diào)用存儲(chǔ)過(guò)程:
exec 存儲(chǔ)過(guò)程名稱 [ (參數(shù)) ]execute 存儲(chǔ)過(guò)程名稱 [ (參數(shù)) ]begin----存儲(chǔ)過(guò)程名稱 [ (參數(shù)) ]end例如:
declarebeginmyproc;end;刪除過(guò)程
drop procedure 過(guò)程名稱獲取過(guò)程返回值
問(wèn)題:給一個(gè)用戶,判斷用戶是否存在--聲明一個(gè)參數(shù)ret,是輸出參數(shù)out,是number類型create or replace procedure myproc2(pid in emp.eid%type,ret out number)asflag number;beginselect count(1) into flag from emp where eid=pid;if flag=1 thendbms_output.put_line(pid||'用戶存在');ret:=1; -- 如果用戶存在就把ret設(shè)為1elsedbms_output.put_line(pid||'用戶不存在');ret:=0; -- 如果用戶不存在就把ret設(shè)為0end if;end;– 調(diào)用過(guò)程
declareinput varchar(50):=('&input');ret number; -- 聲明一個(gè)變量ret,類型是number,用來(lái)存儲(chǔ)過(guò)程的輸出值beginmyproc2(input,ret); -- 獲取到過(guò)程的輸出值存儲(chǔ)在ret中dbms_output.put_line(ret);end;注意:創(chuàng)建過(guò)程中,無(wú)論參數(shù)是輸入?yún)?shù)還是輸出參數(shù),有幾個(gè)參數(shù),在調(diào)用過(guò)程時(shí)就要寫(xiě)多少個(gè)參數(shù)
函數(shù)function
函數(shù)的主要特征是必須有一個(gè)返回值,通過(guò)return來(lái)指定函數(shù)的返回類型,在函數(shù)的任何地方可以通過(guò)return expression語(yǔ)句從函數(shù)返回,返回類型必須和聲明的返回類型一致。
創(chuàng)建函數(shù)
create [ or replace ] function 函數(shù)名稱 [ (參數(shù)列表) ] return 返回值類型{ is | as }----聲明變量begin----執(zhí)行代碼end [函數(shù)名稱];返回大值:
創(chuàng)建函數(shù)create or replace function func_max(num1 in number, num2 in number)return numberisbeginif num1>=num2 thenreturn num1;elsereturn num2;end if;end; 執(zhí)行函數(shù)declarebegindbms_output.put_line(func_max(78,77));end;調(diào)用函數(shù)
declare----創(chuàng)建變量存儲(chǔ)函數(shù)調(diào)用返回值begin----調(diào)用函數(shù)賦值給變量end;刪除函數(shù)
drop function 函數(shù)名稱函數(shù)和過(guò)程區(qū)別
至少返回一個(gè)變量的限制。而存儲(chǔ)過(guò)程可以返回多個(gè),也可以不返回。而函數(shù)是可以嵌入在sql中使用的,可以在select中調(diào)用,而存儲(chǔ)過(guò)程不行。執(zhí)行的本質(zhì)都一樣。
函數(shù)限制比較多,比如不能用臨時(shí)表,只能用表變量.還有一些函數(shù)都不可用等等.而存儲(chǔ)過(guò)程的限制相對(duì)就比較少
一般來(lái)說(shuō),存儲(chǔ)過(guò)程實(shí)現(xiàn)的功能要復(fù)雜一點(diǎn),而函數(shù)的實(shí)現(xiàn)的功能針對(duì)性比較強(qiáng)。
對(duì)于存儲(chǔ)過(guò)程來(lái)說(shuō)可以返回參數(shù),而函數(shù)只能返回值或者表對(duì)象。
存儲(chǔ)過(guò)程一般是作為一個(gè)獨(dú)立的部分來(lái)執(zhí)行(EXEC執(zhí)行),而函數(shù)可以作為查詢語(yǔ)句的一個(gè)部分來(lái)調(diào)用(SELECT調(diào)用),由于函數(shù)可以返回一個(gè)表對(duì)象,因此它可以在查詢語(yǔ)句中位于FROM關(guān)鍵字的后面。
當(dāng)存儲(chǔ)過(guò)程和函數(shù)被執(zhí)行的時(shí)候,SQL Manager會(huì)到procedure cache中去取相應(yīng)的查詢語(yǔ)句,如果在procedure cache里沒(méi)有相應(yīng)的查詢語(yǔ)句,SQL Manager就會(huì)對(duì)存儲(chǔ)過(guò)程和函數(shù)進(jìn)行編譯。
包和包體
創(chuàng)建包
create [ or replace ] package 包名稱 is | as----定義公用常量、變量、過(guò)程、函數(shù)等(不能有具體實(shí)現(xiàn))end [ 包名稱 ];創(chuàng)建包體
create [ or replace ] package body 包名稱 is | as----定義公用常量、變量、過(guò)程、函數(shù)等----實(shí)現(xiàn)公用過(guò)程和函數(shù)end [ 包名稱 ];調(diào)用包
declare----定義變量begin----包名.元素名稱(參數(shù))end刪除包或者包體
drop package [ body ] [ user. ] 包名觸發(fā)器tigger
某個(gè)條件成立時(shí),觸發(fā)器里面定義的語(yǔ)句會(huì)被自動(dòng)執(zhí)行
創(chuàng)建觸發(fā)器
create [or replace] tigger 觸發(fā)器名 { before | after } { insert | update | delete }on 表名 ---- 數(shù)據(jù)庫(kù)觸發(fā)器所在的表。[for each row] ---- 對(duì)表的每一行觸發(fā)器執(zhí)行一次。如果沒(méi)有這一選項(xiàng),則只對(duì)整個(gè)表執(zhí)行一次。begin----pl/sql語(yǔ)句end刪除觸發(fā)器
drop tigger 觸發(fā)器名稱######觸發(fā)器功能???
允許/限制對(duì)表的修改
自動(dòng)生成派生列,比如自增字段
強(qiáng)制數(shù)據(jù)一致性
提供審計(jì)和日志記錄
防止無(wú)效的事務(wù)處理
啟用復(fù)雜的業(yè)務(wù)邏輯
例子:
--創(chuàng)建觸發(fā)器,當(dāng)星期四的時(shí)候不能修改emp表中的數(shù)據(jù)create or replace trigger mytriggerbefore insert or update or deleteon empbeginif to_char(systimestamp,'DY')='星期四' thenraise_application_error(-20001,'今天是星期四,不能修改'); -- -20000 到 -20999之間end if;end;使用觸發(fā)器實(shí)現(xiàn)序號(hào)自增添加數(shù)據(jù)
------創(chuàng)建表create table tbuser(uuid number primary key,uname varchar2(40),upw varchar2(40));------創(chuàng)建序列create sequence myseq increment by 1start with 1001nomaxvaluenocyclecache 20;------創(chuàng)建觸發(fā)器create or replace trigger mytrigger2before inserton tbuserfor each rowdeclare uuuid number;beginselect myseq.nextval into uuuid from dual; -- 獲取序列號(hào):new.uuid:=uuuid; -- :new 表示將要插入的那條記錄 -- :new.uuid 表示新插入記錄的uuidend;寫(xiě)一個(gè)日志表當(dāng)對(duì)tbuser進(jìn)行增加刪除修改的時(shí)候進(jìn)行日志記錄
------創(chuàng)建表create table mylog(l_name varchar(40),l_type varchar(40),l_cdate date);------創(chuàng)建觸發(fā)器create or replace trigger mytrigger3after update or delete or inserton tbuserdeclarec_type mylog.l_type%type;beginif inserting thenc_type:='insert';dbms_output.put_line('插入了數(shù)據(jù)');elsif deleting thenc_type:='delete';dbms_output.put_line('刪除了數(shù)據(jù)');elsif updating thenc_type:='update';dbms_output.put_line('修改了數(shù)據(jù)');end if; insert into mylog values(user,c_type,sysdate);end;創(chuàng)建觸發(fā)器,用來(lái)記錄刪除的數(shù)據(jù)
------創(chuàng)建表create table del_log(uuid number primary key,uname varchar2(40),upw varchar2(40));------創(chuàng)建觸發(fā)器create or replace trigger mytrigger4after delete on tbuserfor each rowdeclarebegininsert into del_log values(:old.uuid,:old.uname,:old.upw); -- :old 表示當(dāng)前記錄 :new表示下一條記錄end;:new 和 :old
:new --為一個(gè)引用最新的列值;
:old --為一個(gè)引用以前的列值; 這兩個(gè)變量只有在使用了關(guān)鍵字 "for each row"時(shí)才存在.且update語(yǔ)句兩個(gè)都有,而insert只有:new ,delect 只有:old;
create or replace trigger uptsalyafter update on empfor each rowbeginif :old.esalary > :new.esalary then ----注意 new 和 old ,new 表示修改后的數(shù)據(jù), old 表示修改前的數(shù)據(jù)dbms_output.put_line('工資降低');elsif :old.esalary < :new.esalary then ----注意 new 和 old ,new 表示修改后的數(shù)據(jù), old 表示修改前的數(shù)據(jù)dbms_output.put_line('工資增加');elsedbms_output.put_line('工資沒(méi)變');end if;dbms_output.put_line('更新前的工資'||:old.esalary);dbms_output.put_line('更新后的工資'||:new.esalary);end;總結(jié)
以上是生活随笔為你收集整理的Oracle-存储过程(procedure、function、package、tigger)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: createjs开发教程
- 下一篇: js-高德地图规划路线