本文旨在把自己學(xué)到的有關(guān)存儲(chǔ)過(guò)程的知識(shí)和大家分享谷浅,并希望能夠幫助正在被存儲(chǔ)過(guò)程折磨的同學(xué)。
什么是存儲(chǔ)過(guò)程
官方定義:
A procedure is a subprogram that performs a specific action
A PL/SQL subprogram is a named PL/SQL block that can be invoked repeatedly. If the subprogram has parameters, their values can differ for each invocation.
A subprogram is either a procedure or a function. Typically, you use a procedure to perform an action and a function to compute and return a value.
翻譯:
存儲(chǔ)過(guò)程是一個(gè)可以執(zhí)行特定行為的子程序
PL/SQL子程序是一個(gè)可以被重復(fù)調(diào)用的擁有名稱的PL/SQL塊(PL/SQL程序都是以塊為基本單位的)奶卓。如果這個(gè)子程序有參數(shù)壳贪,我們則可以在調(diào)用的時(shí)候賦予不同的參數(shù)
子程序可以是存儲(chǔ)過(guò)程或函數(shù)。通常情況下寝杖,你可以使用存儲(chǔ)過(guò)程來(lái)執(zhí)行一個(gè)動(dòng)作,使用函數(shù)來(lái)計(jì)算并返回一個(gè)值
總結(jié):存儲(chǔ)過(guò)程對(duì)于不同的領(lǐng)域的人有不同的理解方式互纯∩唬可以把它理解為一個(gè)指令集,它可以幫助我們完成一系列復(fù)雜的數(shù)據(jù)操作留潦,也可以把它看做一個(gè)專門(mén)處理SQL的批處理工具只盹,在需要的時(shí)候執(zhí)行一些增刪改查的操作。
為什么學(xué)習(xí)存儲(chǔ)過(guò)程
相信在學(xué)習(xí)存儲(chǔ)過(guò)程的你一定已經(jīng)對(duì)普通SQL了如指掌了兔院,簡(jiǎn)單了解了存儲(chǔ)過(guò)程的概念之后殖卑,用普通的SQL與存儲(chǔ)過(guò)程進(jìn)行比較可以讓我們?cè)诠ぷ髦凶龀稣_的選擇。兩者區(qū)別很大坊萝,詳細(xì)的對(duì)比可以問(wèn)度娘孵稽,由于本文主講存儲(chǔ)過(guò)程许起,故羅列一些重要存儲(chǔ)過(guò)程的優(yōu)點(diǎn)如下:
- 降低網(wǎng)絡(luò)的通訊量。如果只是執(zhí)行簡(jiǎn)單的SQL語(yǔ)句的話存儲(chǔ)過(guò)程和普通SQL沒(méi)有太大差別菩鲜,但隨著時(shí)間的推移SQL量越來(lái)越大甚至達(dá)到上百行時(shí)园细,其優(yōu)越性明顯體現(xiàn)
- 提高執(zhí)行效率。我們都知道SQL是先編譯再執(zhí)行的接校,而存儲(chǔ)過(guò)程是預(yù)編譯在服務(wù)器中的猛频,當(dāng)執(zhí)行的時(shí)候跳過(guò)編譯的環(huán)節(jié)效率自然會(huì)提高
- 可維護(hù)性高。更新存儲(chǔ)過(guò)程通常比更新蛛勉,測(cè)試鹿寻,重新部署需要較少的時(shí)間和精力
總之存儲(chǔ)過(guò)程是一個(gè)SQL提供的一個(gè)非常優(yōu)秀的功能,在工作中我們或多或少都會(huì)用到诽凌,學(xué)會(huì)存儲(chǔ)過(guò)程絕對(duì)會(huì)讓你受益匪淺毡熏。
PL/SQL存儲(chǔ)過(guò)程
基本語(yǔ)法
存儲(chǔ)過(guò)程在不同的數(shù)據(jù)庫(kù)語(yǔ)言中語(yǔ)法略有不同,本文針對(duì)ORACLE的PL/SQL皿淋,但其他數(shù)據(jù)庫(kù)語(yǔ)言也是大同小異
上圖是一個(gè)存儲(chǔ)過(guò)程的模型招刹,由此可知一個(gè)最簡(jiǎn)單的存儲(chǔ)過(guò)程必須包含以下關(guān)鍵字CREATE、PROCEDURE窝趣、存儲(chǔ)過(guò)程名稱疯暑、IS/AS、PL/SQLB標(biāo)準(zhǔn)執(zhí)行語(yǔ)句(BEGIN ... END;)哑舒。
通過(guò)不斷的實(shí)踐我們將會(huì)完全理解上圖的含義妇拯。首先從簡(jiǎn)單的存儲(chǔ)過(guò)程開(kāi)始(其功能是向EMP表中添加一條數(shù)據(jù)):
create -- 存儲(chǔ)過(guò)程頭部區(qū)域開(kāi)始
or replace --可選表示如果數(shù)據(jù)庫(kù)中已經(jīng)存在一條相同名稱的存儲(chǔ)過(guò)程就把它替換掉
procedure
proc_emp_create --存儲(chǔ)過(guò)程名稱 procedure_name
(
empno number, ename varchar2, job varchar2, mgr number, hiredate date, sal number, comm number, deptno number
) -- parameter_declaration 聲明參數(shù)(注意不需要寫(xiě)長(zhǎng)度),存儲(chǔ)過(guò)程頭部區(qū)域結(jié)束
as
--聲明區(qū)域洗鸵,不需要聲明變量可以不寫(xiě)
begin -- PL/SQL標(biāo)準(zhǔn)執(zhí)行語(yǔ)句
--執(zhí)行區(qū)域
insert into emp values(empno, ename, job, mgr, hiredate, sal, comm, deptno);
end;
當(dāng)我們執(zhí)行上面的存儲(chǔ)過(guò)程之后這條存儲(chǔ)過(guò)程就被編譯到數(shù)據(jù)庫(kù)中了越锈,進(jìn)入PLSQL Developer中的Procedures文件夾就可以看到我們剛才創(chuàng)建的存儲(chǔ)過(guò)程了
既然存儲(chǔ)過(guò)程已經(jīng)寫(xiě)好并編譯完成了,接下來(lái)就是使用我們創(chuàng)建的存儲(chǔ)過(guò)程了膘滨。使用存儲(chǔ)過(guò)程有兩種方法:
第一種是直接在SQL窗口中甘凭,執(zhí)行SQL語(yǔ)句。
begin
proc_emp_create(7778,'Alexander','analyst',6789,sysdate,4321,'',20);
end;
第二種是在命令窗口中使用execute命令
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as scott
SQL> execute proc_emp_create(7778,'Alexander','analyst',6789,sysdate,4321,'',20);
PL/SQL procedure successfully completed
SQL>
無(wú)論使用哪一種方法火邓,我們都會(huì)發(fā)現(xiàn)在EMP表中已經(jīng)多了一條剛才插入的數(shù)據(jù)丹弱。也就是說(shuō),我們以后想要向EMP表中插入數(shù)據(jù)的話铲咨,就可以直接調(diào)用這條存儲(chǔ)過(guò)程來(lái)執(zhí)行插入操作躲胳。
從上面的例子可以看出,一個(gè)存儲(chǔ)過(guò)程可以分成三個(gè)區(qū)域
- 頭部區(qū)域
用于編寫(xiě)最基本的存儲(chǔ)過(guò)程頭部標(biāo)記纤勒,定義是否要?jiǎng)?chuàng)建一個(gè)替代原有存儲(chǔ)過(guò)程的存儲(chǔ)過(guò)程坯苹;決定是否定義參數(shù);定義參數(shù)的類型(in out inout)摇天;定義執(zhí)行權(quán)限(Schema)粹湃。 - 聲明區(qū)域
用于聲明變量(要定義長(zhǎng)度)包括cursor恐仑; - 執(zhí)行區(qū)域
用于執(zhí)行業(yè)務(wù)邏輯代碼,可以使用條件語(yǔ)句(選擇再芋、判斷菊霜、循環(huán)。济赎。鉴逞。)來(lái)進(jìn)行一些業(yè)務(wù)邏輯CRUD的處理
繼續(xù)實(shí)踐
了解了存儲(chǔ)過(guò)程的基本語(yǔ)法和用途之后,再通過(guò)一些簡(jiǎn)單的實(shí)例可以幫助我們更好的理解存儲(chǔ)過(guò)程的語(yǔ)法和其含義司训。上面的例子簡(jiǎn)單的完成了對(duì)EMP表的添加功能构捡,接下來(lái)將會(huì)使用存儲(chǔ)過(guò)程對(duì)EMP進(jìn)行刪除、修改和查詢功能壳猜,實(shí)現(xiàn)完整的CRUD
D
創(chuàng)建用于根據(jù)EMPNO刪除EMP中一條數(shù)據(jù)的存儲(chǔ)過(guò)程
create or replace procedure proc_emp_delete(deleteid number) as
begin
delete from emp where empno = deleteid;
end;
執(zhí)行(兩種方法任選其一即可)
begin
proc_emp_delete(7778);
end;
執(zhí)行完成之后勾徽,剛才我們?cè)诹私獯鎯?chǔ)過(guò)程語(yǔ)法的那條數(shù)據(jù)就被刪除了
U
接下來(lái)來(lái)寫(xiě)更新的存儲(chǔ)過(guò)程,首先準(zhǔn)備一條數(shù)據(jù)
begin
proc_emp_create(7778,'Alexander','analyst',6789,sysdate,4321,'',20);
end;
執(zhí)行之后剛才被我們刪掉的數(shù)據(jù)就又重新插入到EMP表中统扳,接下來(lái)寫(xiě)更新的存儲(chǔ)過(guò)程
create or replace procedure
proc_emp_update
(
p_empno number, p_ename varchar2, p_job varchar2, p_mgr number, p_hiredate date, p_sal number, p_comm number, p_deptno number
)
as
begin
update emp set ename = p_ename,job = p_job,mgr = p_mgr,hiredate=p_hiredate,sal = p_sal,comm=p_comm,deptno = p_deptno where empno=p_empno;
end;
需要注意的是參數(shù)不能和字段表的名稱相同喘帚,接下來(lái)執(zhí)行
begin
proc_emp_update(7778,'Alexander','analyst','6789',sysdate,4321,3000,10);
end;
再次查詢會(huì)發(fā)現(xiàn)Alexander的獎(jiǎng)金多了3000塊。
R
最后要做的就是查詢了咒钟,對(duì)于多條數(shù)據(jù)的查詢輸出要使用cursor吹由,留在下篇文章中討論,我們先做一個(gè)最簡(jiǎn)單的單條數(shù)據(jù)查詢
create or replace procedure proc_emp_read
as
v_no number;--聲明變量
begin
select count(empno) into v_no from emp;--在執(zhí)行代碼塊里面查詢一定要使用into賦值
dbms_output.put_line(v_no);
end;
接下來(lái)執(zhí)行
begin
proc_emp_read;
end;
我的結(jié)果如下圖所示:
至此朱嘴,簡(jiǎn)單的CRUD實(shí)踐就完成了倾鲫,相信你已經(jīng)對(duì)存儲(chǔ)過(guò)程有了大概的理解并能寫(xiě)出簡(jiǎn)單存儲(chǔ)過(guò)程了。當(dāng)然這只是存儲(chǔ)過(guò)程最基本的使用方法萍嬉,其高級(jí)特性(cursor乌昔、schema、控制語(yǔ)句壤追、事務(wù)等)將在下篇文章中討論磕道。