本文旨在把自己學到的有關存儲過程的知識和大家分享,並希望能夠幫助正在被存儲過程折磨的同學。
什么是存儲過程
官方定義:
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.
翻譯:
存儲過程是一個可以執行特定行為的子程序
PL/SQL子程序是一個可以被重復調用的擁有名稱的PL/SQL塊(PL/SQL程序都是以塊為基本單位的)。如果這個子程序有參數,我們則可以在調用的時候賦予不同的參數
子程序可以是存儲過程或函數。通常情況下,你可以使用存儲過程來執行一個動作,使用函數來計算並返回一個值
總結:存儲過程對於不同的領域的人有不同的理解方式。可以把它理解為一個指令集,它可以幫助我們完成一系列復雜的數據操作,也可以把它看做一個專門處理SQL的批處理工具,在需要的時候執行一些增刪改查的操作。
為什么學習存儲過程
相信在學習存儲過程的你一定已經對普通SQL了如指掌了,簡單了解了存儲過程的概念之后,用普通的SQL與存儲過程進行比較可以讓我們在工作中做出正確的選擇。兩者區別很大,詳細的對比可以問度娘,由於本文主講存儲過程,故羅列一些重要存儲過程的優點如下:
- 降低網絡的通訊量。如果只是執行簡單的SQL語句的話存儲過程和普通SQL沒有太大差別,但隨着時間的推移SQL量越來越大甚至達到上百行時,其優越性明顯體現
- 提高執行效率。我們都知道SQL是先編譯再執行的,而存儲過程是預編譯在服務器中的,當執行的時候跳過編譯的環節效率自然會提高
- 可維護性高。更新存儲過程通常比更新,測試,重新部署需要較少的時間和精力
總之存儲過程是一個SQL提供的一個非常優秀的功能,在工作中我們或多或少都會用到,學會存儲過程絕對會讓你受益匪淺。
PL/SQL存儲過程
基本語法
存儲過程在不同的數據庫語言中語法略有不同,本文針對ORACLE的PL/SQL,但其他數據庫語言也是大同小異
上圖是一個存儲過程的模型,由此可知一個最簡單的存儲過程必須包含以下關鍵字CREATE、PROCEDURE、存儲過程名稱、IS/AS、PL/SQLB標准執行語句(BEGIN ... END;)。
通過不斷的實踐我們將會完全理解上圖的含義。首先從簡單的存儲過程開始(其功能是向EMP表中添加一條數據):
create -- 存儲過程頭部區域開始
or replace --可選表示如果數據庫中已經存在一條相同名稱的存儲過程就把它替換掉
procedure
proc_emp_create --存儲過程名稱 procedure_name
(
empno number, ename varchar2, job varchar2, mgr number, hiredate date, sal number, comm number, deptno number
) -- parameter_declaration 聲明參數(注意不需要寫長度),存儲過程頭部區域結束
as
--聲明區域,不需要聲明變量可以不寫
begin -- PL/SQL標准執行語句
--執行區域
insert into emp values(empno, ename, job, mgr, hiredate, sal, comm, deptno);
end;
當我們執行上面的存儲過程之后這條存儲過程就被編譯到數據庫中了,進入PLSQL Developer中的Procedures文件夾就可以看到我們剛才創建的存儲過程了
既然存儲過程已經寫好並編譯完成了,接下來就是使用我們創建的存儲過程了。使用存儲過程有兩種方法:
第一種是直接在SQL窗口中,執行SQL語句。
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>
無論使用哪一種方法,我們都會發現在EMP表中已經多了一條剛才插入的數據。也就是說,我們以后想要向EMP表中插入數據的話,就可以直接調用這條存儲過程來執行插入操作。
從上面的例子可以看出,一個存儲過程可以分成三個區域
- 頭部區域
用於編寫最基本的存儲過程頭部標記,定義是否要創建一個替代原有存儲過程的存儲過程;決定是否定義參數;定義參數的類型(in out inout);定義執行權限(Schema)。 - 聲明區域
用於聲明變量(要定義長度)包括cursor; - 執行區域
用於執行業務邏輯代碼,可以使用條件語句(選擇、判斷、循環。。。)來進行一些業務邏輯CRUD的處理
繼續實踐
了解了存儲過程的基本語法和用途之后,再通過一些簡單的實例可以幫助我們更好的理解存儲過程的語法和其含義。上面的例子簡單的完成了對EMP表的添加功能,接下來將會使用存儲過程對EMP進行刪除、修改和查詢功能,實現完整的CRUD
D
創建用於根據EMPNO刪除EMP中一條數據的存儲過程
create or replace procedure proc_emp_delete(deleteid number) as
begin
delete from emp where empno = deleteid;
end;
執行(兩種方法任選其一即可)
begin
proc_emp_delete(7778);
end;
執行完成之后,剛才我們在了解存儲過程語法的那條數據就被刪除了
U
接下來來寫更新的存儲過程,首先准備一條數據
begin
proc_emp_create(7778,'Alexander','analyst',6789,sysdate,4321,'',20);
end;
執行之后剛才被我們刪掉的數據就又重新插入到EMP表中,接下來寫更新的存儲過程
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;
需要注意的是參數不能和字段表的名稱相同,接下來執行
begin
proc_emp_update(7778,'Alexander','analyst','6789',sysdate,4321,3000,10);
end;
再次查詢會發現Alexander的獎金多了3000塊。
R
最后要做的就是查詢了,對於多條數據的查詢輸出要使用cursor,留在下篇文章中討論,我們先做一個最簡單的單條數據查詢
create or replace procedure proc_emp_read
as
v_no number;--聲明變量
begin
select count(empno) into v_no from emp;--在執行代碼塊里面查詢一定要使用into賦值
dbms_output.put_line(v_no);
end;
接下來執行
begin
proc_emp_read;
end;
我的結果如下圖所示:
至此,簡單的CRUD實踐就完成了,相信你已經對存儲過程有了大概的理解並能寫出簡單存儲過程了。當然這只是存儲過程最基本的使用方法,其高級特性(cursor、schema、控制語句、事務等)將在下篇文章中討論。