基於Oracle數據庫存儲過程的創建及調用
1.PLSQL編程
1.1 概念和目的
什么是PL/SQL?
- PL/SQL(Procedure Language/SQL)
- PLSQL是oracle對sql語言的過程化擴展(類似於Basic)
- 指在SQL命令語言中增加了過程處理語句(如分支、循環等),使SQL語句具有過程處理能力。
1.2 程序結構
通過Plsql developer 工具盒Tset Window創建 程序模板或者用過語句在SQL windows編寫。
提示:PLSQL語言的大小寫是不區分的
PL/SQL 可以分為三個部分:聲明部分、可執行部分、異常處理部分
-- Created on 2019/10/31 by ADMINISTRATOR
declare
-- Local variables here(聲明變量,游標)
i integer;
begin
-- Test statements here(處理異常)
end;
其中declare 部分用來聲明變量和游標(結果集類型變量),如果程序中無變量聲明可去掉。
1.3 Hello World
begin
-- Test statements here
--java system.out.println("hello world");
dbms_output.put_line('hello world');
end;
dbms_output為oracle內置程序包,相當於Java中的System.out,而PUT_LINE()是調用方法,相當於println()方法
在sqlplus中也可以編寫運行PLSQL程序
SQL>begin
-- Test statements here
--java system.out.println("hello world");
dbms_output.put_line('hello world');
end;
/
執行結束后並未顯示輸出的結果,默認情況下,輸出選項是關閉狀態的,我們需要開啟一下 set serveroutput on
SQL>set serveroutput on
SQL>begin
-- Test statements here
--java system.out.println("hello world");
dbms_output.put_line('hello world');
end;
/
SQLPLUS中執行PLSQL程序,需要在程序最后添加一個/標識程序的結束。
1.4 變量
PLSQL編程中常見的變量分為兩大類:
1.普通數據類型(char,varchar2,date,number,boolean,long)
2.特殊變量類型(引用型變量、記錄型變量)
聲明變量的方式為
1 變量名 變量類型(變量長度) 例如: v_name varchar2(20);
1.4.1 普通變量
變量賦值的方式有兩種
1.直接賦值語句 := 比如 : v_name :='zhangsan'
2.語句賦值,使用select... into... 賦值: (語法select 值 into 變量);
【示例】 打印人員個人信息,包括:姓名、薪水、地址
--打印人員個人信息,包括:姓名、薪水、地址
-- Created on 2019/10/31 by ADMINISTRATOR
declare
v_name varchar(20) :='張三';
v_val number;
v_addr varchar(300);
begin
v_val :='10000';
select '合肥' into v_addr from dual;
dbms_output.put_line('姓名:'||v_name||',薪水:'||v_val||',地址:'||v_addr);
end;
1.4.2 引用型變量
變量的類型和長度取決於表中字段的類型和長度
通過表名.列名%TYPE指定變量的類型和長度,例如 v_name emp.ename%TYPE;
【示例】查詢emp表中7839號員工的個人信息,打印姓名和薪水
-- 查詢emp表中7839號員工的個人信息,打印姓名和薪水
declare
--姓名
v_name emp.ename%TYPE;
--薪水
v_sal emp.sal%TYPE;
begin
--查詢表中的姓名和薪水並賦值給變量
--注意查詢的字段和賦值的變量的順序、個數、類型要一致
select ename, sal
into v_name, v_sal
from emp
where empno = 7839;
-- 打印輸出
dbms_output.put_line('姓名:' || v_name || ',薪水:' || v_sal);
end;
引用型變量的好處:
使用普通變量定義方式,需要知道表中列的類型,而使用引用類型,不需要考慮列的類型,使用%TYPE是非常好的編程風格,因為它使得PL/SQL更加靈活,更加適應於對數據庫定義的更新。
1.4.3 記錄型變量
接收表中的一整行記錄,相當於java中的一個對象
語法:變量名稱 表名%ROWTYPE, 例如 v_emp emp%ROWTYPE
【示例】
查詢並打印7839號員工的姓名和薪水
-- 查詢emp表中7839號員工的個人信息,打印姓名和薪水
declare
--記錄型變量接收一行
v_emp EMP%TYPE
begin
--記錄型變量默認接收表中的一行數據,不能指定字段
select *
into v_emp
from emp
where empno = 7839
dbms_output.put_line('姓名:' || v_emp.ename || ',薪水:' || v_emp.sal);
end;
優點:如果有一個表,有100個字段,那么你程序如果要使用這100字段話,如果你使用引用型變量一個個聲明,會特別麻煩,記錄型變量可以方便的解決這個問題
錯誤的使用
1.記錄型變量只能存儲一個完整的行數據。
2.返回的行太多,也記錄不了
1.5 流程控制
1.5.1 條件分支
語法:
BEGIN
IF 條件1 then 執行1
elsif 條件 2 then 執行2
else 執行3
end if;
end;
注意關鍵字:ELSIF
【示例】判斷emp表中是否超過20條,10-20之間,或者10條以下
-- 判斷emp表中是否超過20條,10-20之間,或者10條以下
declare
--聲明變量接收emp表中的數量
v_count number;
begin
--查詢emp表中的記錄數賦值給變量
select count(1) into v_count from emp;
--判斷打印
if v_count > 20 then
dbms_output.put_line('emp表中的記錄數據超過20條為:' || v_count);
elsif v_count >= 10 then
dbms_output.put_line('emp表中的記錄數為10-20之間,為:' || v_count);
else
dbms_output.put_line('emp表中的記錄數為10以下,為:' || v_count);
end if;
end;
1.5.2 循環
在oracle中有三種循環方式,只介紹一種:loop循環
語法:
begin
loop
exit when 退出循環條件
end loop;
end;
【示例】 打印數字1-10
declare
--聲明循環變量並賦初值
v_num number :=1;
begin
loop
exit when v_num >10;
dbms_output.put_line(v_num);
-- 循環變量自增
v_num :=v_num+1;
end loop;
end;
2 游標
2.1 什么是游標
用於臨時存儲一個查詢返回的多行數據(結果集,類似於java的jdbc鏈接返回額ResultSet集合),通過遍歷游標,可以逐行訪問處理該結果集的數據。
游標的使用方式:聲明-->打開-->讀取-->關閉
2.2 語法
游標聲明:
CURSOR 游標名[(參數列表)] IS 查詢語句;
游標的打開:
open 游標名;
游標的取值;
FETCH 游標名 INTO 變量列表;
游標的關閉:
CLOSE 游標名;
2.3 游標的屬性
游標的屬性 | 返回值類型 | 說明 |
---|---|---|
%ROWCOUNT | 整型 | 獲得FETCH語句返回的數據行數 |
%FOUND | 布爾型 | 最近的FETCH語句返回一行數據則為真,否則為假 |
%NOTFOUND | 布爾型 | 與%FOUND屬性返回值相反 |
%ISOPEN | 布爾型 | 游標已經打開時值為真,否則為假 |
其中%NOTFOUND 是在游標中找不到元素的時候返回TRUE,通常用來判斷退出循環。
2.4 創建和使用
【示例】使用游標查詢emp表中所有員工的姓名和工資,並且將其依次打印出來
--使用游標查詢emp表中所有員工的姓名和工作,並將其依次打印出來
declare
--聲明游標
CURSOR C_EMP IS SELECT ENAME,SAL FROM EMP;
--聲明變量用來接收游標中的元素
V_NAME EMP.ENAME%TYPE;
V_SAL EMP.SAL%TYPE;
begin
--打開游標
OPEN C_EMP;
--遍歷游標中的值
LOOP
--通過FETCH語句獲取游標中的值並賦值給變量
FETCH E_EMP
INTO V_NAME,V_SAL;
--通過%NOTFOUND判斷是否有值,有值打印,沒有則則退出循環
EXIT WHEN C_EMP%NOTFOUND;
DBMS_OUTPUT.put_line('姓名:'||V_NAME||',薪水:'V_SAL);
END LOOP;
--關閉游標
CLOSE C_EMP;
END;
執行結果:
2.5 帶參數的游標
【示例】查詢某個部門的所有員工的姓名和工作,並將其依次打印出來
--使用游標查詢emp表中所有員工的姓名和工作,並將其依次打印出來
declare
--聲明游標 添加判斷語句WHERE deptno=v_deptno 並且賦值給游標C_EMP
CURSOR C_EMP(v_deptno emp.deptno%TYPE) IS SELECT ENAME,SAL FROM EMP WHERE deptno=v_deptno;
--聲明變量用來接收游標中的元素
V_NAME EMP.ENAME%TYPE;
V_SAL EMP.SAL%TYPE;
begin
--打開游標
OPEN C_EMP(10);
--遍歷游標中的值
LOOP
--通過FETCH語句獲取游標中的值並賦值給變量
FETCH E_EMP
INTO V_NAME,V_SAL;
--通過%NOTFOUND判斷是否有值,有值打印,沒有則則退出循環
EXIT WHEN C_EMP%NOTFOUND;
DBMS_OUTPUT.put_line('姓名:'||V_NAME||',薪水:'V_SAL);
END LOOP;
--關閉游標
CLOSE C_EMP;
END;
注意:%NOTFOUND 屬性默認值為Flase,所以在循環中要注意判斷條件的位置,如果先判斷在FETCH會導致最后一條記錄的值被打印兩次(多循環一次默認);
3 存儲過程
3.1 概念作用
上面我們編寫的PLSQL程序可以進行表的操作,判斷,循環邏輯處理的工作,但無法重復調用。
可以理解之前的代碼全都編寫在了main方法中,是匿名程序,JAVA可以通過封裝對象和方法來解決復用問題
PLSQL是將一個個PLSQL的業務處理過程存儲起來進行復用,這些被存儲起來的的PLSQL程序稱之為存儲過程。
存儲過程作用
1.在開發程序中,為了一個特定的業務功能,會向數據庫進行 多次連接關閉(連接和關閉是很耗費資源),需要對數據庫進行多次的I/O讀寫,性能比較低。如果把這些業務放到PL/SQL中,在應用程序中只需要調用PLSQL就可以做到連接關閉一次數據庫就可以實現我們的業務,可以大大提高效率。
2.ORACLE官方給的建議:能夠讓數據庫操作的不要放在程序中,在數據庫中實現基本上不會出現錯誤,在程序中操作可能會存在錯誤(如果在數據庫中操作數據,可以有一定的日志恢復等功能)、
3.2 語法
CREATE OR REPLACE PROCEDURE 過程名稱[(參數列表)] IS
BEGIN
END[過程名稱];
根據參數的類型,可以分為三種
不帶參數的
帶輸入參數的
帶輸入輸出參數(返回值)的
3.3 無參存儲
3.3.1 創建存儲
通過Plsql Developer 或者語句創建存儲過程:
【示例】通過調用存儲過程打印hello world
創建存儲過程:
--通過調用存儲過程打印hello world
create or replace procedure P_HELLO AS
BEGIN
DBMS_OUTPUT.PUT_LINE('hello world');
END
通過工具查看創建好的存儲過程;
3.3.2 調用存儲過程
1.通過PLSQL程序可調用:
begin
--直接輸入調用存儲過程的名稱
P_HELLO
end
2.在sqlplus中通過exec命令調用:
提示:sqlplus中顯示結果的前提是需要set serveroutput on
注意:
第一個問題:is和as是可以互用的,用哪個都沒關系的
第二個問題:過程中沒有declare關鍵字,declare用在語句塊中。
3.4 帶輸入參數的存儲過程
【實例】查詢並打印某個員工的姓名和薪水--存儲過程:要求,調用額時候傳入員工編號,自動控制台打印
--查詢並打印某個員工的姓名和薪水--存儲過程:要求,調用額時候傳入員工編號,自動控制台打印
create or replace procedure p_querynameandsal(i_empno in emp.empno%TYPE) AS
--聲明變量
v_name emp.ename%TYPE;
v_sal emp.sal%TYPE;
begin
--查詢emp表中某個員工的姓名和薪水並賦值給變量
select ename,sal into v_name,v_sal from emp where empno=i_empno;
dbms_output.put_line('姓名:'||v_name||',薪水:'||v_sal);
END p_querynameandsal;
調用
begin
p_querynameandsal(7839);
end
3.5 帶輸出參數的存儲過程
【示例】輸入員工號查詢某個員工信息,要求將薪水作為返回值輸出,給調用的程序使用。
--輸入員工號查詢某個員工信息,要求將薪水作為返回值輸出,給調用的程序使用。
create or replace procedure p_querysal_out(i_empno in emp.empno%TYPE,o_sal out emp.sal%TYPE) AS
begin
--查詢emp表中某個員工的姓名和薪水並賦值給變量
select sal into o_sal from emp where empno=i_empno;
END p_querysal_out;
PL/SQL調用
declare
v_sal emp.sal%TYPE;
begin
p_querysal_out(7839,v_sal);
dbms_output.put_line(v_sall);
end