文章目錄
一、基礎介紹
- 存儲過程和函數也是數據庫對象,是存儲在數據庫中的被命名的PLSQL塊,供所有用戶程序調用完成特定功能的子程序。
- 存儲過程類似java中的void方法,主要用途是功能的處理,存儲該函數類似非void方法,需要return返回值。
二、存儲過程
(一) 創建和調用
語法
CREATE [OR REPLACE] PROCEDURE 過程名
[(參數名1 IN|OUT|IN OUT 參數值類型 [DEFAULT 默認值]),
(參數名2 IN|OUT|IN OUT 參數值類型[DEFAULT 默認值])...]
AS|IS
[變量名 變量類型[:=初始值]; --聲明變量部分 ]
BEGIN
執行部分;
[EXCEPTION
異常錯誤處理部分;]
END;
1.無參的存儲過程
1)創建
--創建存儲過程(無參)
CREATE OR REPLACE
PROCEDURE first_proc2 is--
BEGIN
DBMS_OUTPUT.PUT_LINE('我是過程2');--打印內容
DBMS_OUTPUT.PUT_LINE('hello everyone!');
END;
2)調用
BEGIN
first_proc2;
end;
2.帶輸入參數的存儲過程in
1)創建
create or replace procedure proc_inparams
(v_empno in EMPNEW.EMPNO%TYPE)--名稱是v_empno的In類型的參數,TYPE與emp_1表的empno字段相同
IS
begin
--根據員工號刪除指定員工信息
delete from EMPNEW where empno=v_empno;--一般不用在程序中commit和rollback
--判斷是否成功
if SQL%NOTFOUND then
-- -20000~20999之間
RAISE_APPLICATION_ERROR(-20008,'指定刪除的員工不存在');--內置的存儲過程,用於在子程序中指定錯誤的自定義信息,錯誤號和錯誤提示內容可以自定義
ELSE
DBMS_OUTPUT.PUT_LINE('刪除成功');
END IF;
end;
2)調用
BEGIN
PROC_INPARAMS(1234);--調用時傳參
end;
DECLARE
dpn number:=1234;
BEGIN
PROC_INPARAMS(dpn);
end;
3.帶輸出過程的存儲過程out
1)創建
create or replace procedure proc_outparams
(v_deptno in number,v_avgsal out number,v_cnt out number)
AS
BEGIN
select avg(sal),count(*) into v_avgsal,v_cnt --參數變量賦值into
from EMP
where deptno=v_deptno;
EXCEPTION
when NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line('無此部門');
when others THEN
DBMS_OUTPUT.put_line(SQLERRM);
END;
2)調用
DECLARE
v_avgsalary number;--聲明兩個變量用於接收out參數
v_count number;
BEGIN
PROC_OUTPARAMS(10,v_avgsalary,v_count);--位置傳值,聲明的變量按照順序對應接收out參數
DBMS_OUTPUT.put_line('平均工資:'||v_avgsalary);
DBMS_OUTPUT.put_line('總人數:'||v_count);
end;
4.帶輸入輸出過程的存儲過程in out
1)創建
create or replace procedure proc_inoutparams
(v_num1 in out number,v_num2 in out number)
as
v_temp number:=0;--聲明一個叫v_temp的變量,type是NUMBER,賦值0
BEGIN
--交換兩個數
v_temp:=v_num1;
v_num1:=v_num2;
v_num2:=v_temp;
end;
2)調用
DECLARE
v_n1 number:=5;--聲明兩個變量用於接收參數
v_n2 number:=8;
BEGIN
PROC_INOUTPARAMS(v_n1,v_n2);--聲明的變量按照順序對應接收in out參數
DBMS_OUTPUT.put_line('v_n1:'||v_n1);
DBMS_OUTPUT.put_line('v_n2:'||v_n2);
end;
(二) 刪除
drop procedure "first_proc";--過程名區分是否有引號
三、存儲函數
(一) 創建和調用
語法
CREATE [OR REPLACE] FUNCTION 函數名
[(參數名1 IN|OUT|IN OUT 參數值類型 [DEFAULT 默認值]),
(參數名2 IN|OUT|IN OUT 參數值類型 [DEFAULT 默認值])...]
RETURN 返回值類型--比過程多的部分
AS|IS
[變量名 變量類型[:=初始值]; --聲明變量部分 ]
BEGIN
執行部分;
[EXCEPTION
異常錯誤處理部分;]
END;
1.無參的存儲函數
1)創建
CREATE OR REPLACE function "first_func2"
return VARCHAR2
iS
BEGIN
DBMS_OUTPUT.PUT_LINE('我是函數2');
return 'hello,everyone';--對應之前的類型
END;
2)調用
BEGIN
dbms_output.put_line(first_func2);
end;
2.帶輸入參數的存儲函數in
1)創建
create or replace function func_inparams
(v_deptno in number)
return NUMBER
is
v_sumsal number;--聲明變量
BEGIN
--根據部門編號返回部門總工資
select sum(sal) into v_sumsal from emp where DEPTNO=v_deptno;--變量賦值
return v_sumsal;--返回變量
EXCEPTION
when no_data_found THEN
dbms_output.put_line('無此部門');
when others THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
2)調用
BEGIN
dbms_output.put_line('部門工資總和:'||FUNC_INPARAMS(10));
end;
3.帶輸出過程的存儲函數out
1)創建
create or replace function func_outparams
(v_empno in EMP.EMPNO%type, v_name out EMP.ENAME%type,v_sal out EMP.SAL%type )
return number
AS
v_yasal number;
BEGIN
--根據員工號輸出員工姓名和工資,並返回員工的年收入
select ename,sal,(sal+nvl(comm,0))*12 into v_name,v_sal,v_yasal
from EMP
where empno=v_empno;
return v_yasal;
EXCEPTION
when no_data_found THEN
dbms_output.put_line('無此員工');
when others THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
2)調用
DECLARE
v_name EMP.ENAME%type;--聲明兩個變量用於接收out參數
v_sal EMP.SAL%type;
v_yasal number;
BEGIN
v_yasal:=FUNC_OUTPARAMS(7369,v_name,v_sal);
dbms_output.put_line('姓名'||v_name||'的工資是'||v_sal||',年總收入是:'||v_yasal);
end;
4.帶輸入輸出過程的存儲函數in out
1)創建
create or replace function func_inoutparams
(n1 in out number,n2 in out number)
return NUMBER
AS
BEGIN
n1:=n1*n1;
n2:=n2*n2;
return n1+n2;
end;
2)調用
DECLARE
v_n1 number :=5;
v_n2 number :=8;
BEGIN
dbms_output.put_line(v_n1||'和'||v_n2||'的和是:'||FUNC_INOUTPARAMS(v_n1, v_n2));--此時v_n1和v_n2已經參與函數計算
end;
(二) 刪除
drop function "first_func";
四、使用DEFAULT默認值
1.單個參數
--------------------------------求部門的年收入----------------------
--創建
CREATE OR REPLACE
function func_defa
(v_deptno in number DEFAULT 10)
return NUMBER
AS
v_deptysal number;
BEGIN
select sum(sal+nvl(comm,0))*12 into v_deptysal
from emp where deptno=v_deptno;
return v_deptysal;
EXCEPTION
when NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line('沒有此部門');
when others THEN
DBMS_OUTPUT.put_line(SQLERRM);
end;
--調用
BEGIN
dbms_output.put_line('部門年收入總和:'||FUNC_DEFA);--使用默認值,不用傳參
dbms_output.put_line('部門年收入總和:'||FUNC_DEFA(20));--不用默認值,需要傳參
end;
2.多個參數
---------------------------求部門的年收入---------------------
--創建
CREATE OR REPLACE
function func_defa2
(v_deptno in number DEFAULT 10,v_test in number)
return NUMBER
AS
v_deptysal number;
BEGIN
select sum(sal+nvl(comm,0))*12 into v_deptysal
from emp where deptno=v_deptno;
DBMS_OUTPUT.put_line('測試:'||v_test);
return v_deptysal;
EXCEPTION
when NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line('沒有此部門');
when others THEN
DBMS_OUTPUT.put_line(SQLERRM);
end;
--調用
BEGIN
--dbms_output.put_line('部門年收入總和:'||FUNC_DEFA2(,888));--第一個參數省略時,位置傳值,報錯,不能這樣傳
dbms_output.put_line('部門年收入總和:'||FUNC_DEFA2(v_test=>888));--名稱傳值,關聯符號=>
end;
五、比較
1.關鍵字
創建過程:procedure
創建函數:function
2.調用方式
存儲過程使用獨立的調用語句
begin
proc1
end;
存儲函數以表達式方式調用
declare
v_result NUMBER;
begin
v_result:=func1;
end;
4.return返回值
存儲函數通過return語句返回函數值,存儲過程則沒有
5.用途
存儲過程的目的是完成一系列的數據處理;存儲函數的目的是獲得函數返回值。
6.參數
過程和函數都可以有一個或多個out輸出函數。
存儲過程沒有return語句,但是可以通過out參數來實現返回值。
一般原則,如果只有一個返回值,用存儲函數處理