1. 程式人生 > >oracle 儲存過程和函式的呼叫方法

oracle 儲存過程和函式的呼叫方法

一.儲存過程(PROCEDURE)
使用過程, 不僅可以簡化客戶端應用程式的開發和維護,而且可以提高應用程式的執行效能.
CREATE [OR REPLACE] PROCUDURE procedure_name
(arg1 [model1] datatype1, arg2[model2] datatype2)
IS [AS]
PL/SQL Block;
arg1,arg2用於指定過程的引數,IS/AS用於開始一個PL/SQL塊.當指定引數資料型別時,不能指定其長度.
在建立過程的時間,既可以指定輸入引數(IN),也可以指定輸出引數(OUT)以及輸入輸出引數(IN OUT).如果不定義引數模式,則預設為輸入引數,如果要定義輸出引數,則需要指定OUT關鍵字,如果定義輸入輸出引數,

要指定IN OUT關鍵字.
一般使用execute(或exec) 過程名 或者 call 過程名來呼叫過程.
set serveroutput on開啟Oracle的輸出.
(1)不帶引數的過程
CREATE OR REPLACE PROCEDURE out_time
IS
BEGIN    
dbms_output.put_line(systimestamp);
END;

call out_time();或者 exec out_time;
(2)帶IN引數的過程
如果不指定引數模式,則預設的為IN,也可以顯示的指定輸入模式IN.
CREATE OR REPLACE PROCEDURE add_employee
(eno NUMBER,name VARCHAR2,sal NUMBER,job VARCHAR2 DEFAULT 'CCC', dno NUMBER)

IS
BEGIN
INSERT INTO emp(empno, ename,sal,job,deptno)
VALUES(eno,ename,sal,job,dno);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20000, '僱員不能重複');
END;
除了預設值的引數外,其餘的都要輸入.
(3)帶OUT的過程
在過程中輸出結果是使用OUT或者IN OUT來完成的.
定義輸出引數的時間,必須要使用OUT來定義輸出.
CREATE OR REPLACE PROCEDURE query_employee
(eno NUMBER,name OUT VARCHAR2,sal OUT NUMBER)

IS
BEGIN
SELECT ename, sal INTO name, sal FROM emp WHERE empno=eno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20000, '僱員不存在');
END;
對於指定為OUT型別的引數,必須定義變數接收輸出引數的資料.呼叫例項:
SQL> var name VARCHAR2(10)
SQL> var sal NUMBER
SQL> exec query_employee(77,:name,:sal)
SQL> print name sal
(4)帶IN和OUT的過程
在呼叫前要通過變數給引數傳遞資料,在呼叫結束後,會通過此變數將值傳遞給應用程式
CREATE OR PROCEDURE compute
(num IN OUT NUMBER, num2 IN OUT NUMBER)
IS 
v1 NUMBER;
v2 NUMBER;
BEGIN
v1:=num1/num2;
v2:=MOD(num1, num2);
num1 := v1;
num2 := v2;
END;
在應用程式呼叫IN OUT的儲存過程時,必須提供兩個變數臨時存放數值,執行如下:
SQL> var n1 NUMBER
SQL> var n2 NUMBER
SQL> exec :n1:=100
SQL> exec :n2:=30
SQL> exec compute(:n1, :n2)
SQL> PRINT n1 n2
(5)為引數傳遞變數和資料
[1]位置傳遞
如 SQL> exec add_dept(50, 'SALES', 'NEW YORK')
[2]名稱傳遞,使用=>符號來指定值
如 SQL> exec add_dept(dno=>50)
[3]組合傳遞,以上兩種傳遞方法交替
(6)檢視過程的原始碼
過程名,原始碼,執行程式碼放到了資料字典中,通過查詢資料字典USER_SOURCE,可以顯示當前使用者定義的過程
SELECT text FROM user_source WHERE name='ADD_DEPT';
(7)刪除過程
DROP PROCEDURE 過程名

二.函式(FUNCTION)
CREATE [OR REPLACE] FUNCTION function_name
(arg1 [model1] datatype1,arg2 [model2] datatype2)
RETURN datatype
IS|AS
PL/SQL Block;
arg1,arg2指定函式的引數,當不指定引數資料型別時,不能指定其長度
RETURN 指定函式返回的資料型別.注意,函式前面必須要有RETURN子句.在函式體內至少含有一條RETURN子句.函式的引數MODEl和過程的一樣
(1)不帶引數的函式
CREATE OR REPLACE FUNCTION get_user
RETURN VARCHAR2
IS
v_user VARCHAR2(100);
BEGIN
SELECT username INTO v_user FROM user_users;
RETURN v_user;
END;
呼叫方法
SQL> var v1 VARCHAR2(100)
SQL> exec :v1:=get_user
SQL> PRINT v1
(2)帶IN引數
CREATE OR REPLACE FUNCTION get_sal(name IN VARCHAR2)
RETURN NUMBER
IS
v_sal emp.sal%TYPE;
BEGIN
SELECT sal INTO v_sal FROM emp
WHERE upper(ename)=upper(name);
RETURN v_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise-application_error(-20000,'該僱員不存在');
END;
呼叫方法如下:
SQL> var sal NUMBER
SQL> exec :sal:=get_sal('scott')
SQL> print sal
(3)帶OUT引數
一般情況下,函式只需要單個返回資料,如果希望使用函式同事返回多個數據,就需要用到輸出引數了.
CREATE OR REPLACR FUNCTION get_info 
(name VARCHAR2, title OUT VARCHAR2)
RETURN VARCHAR2
AS
deptname dept.dname%TYPE;
BEGIN
SELECT a.job,b.dname INTO title, deptname
FROM emp a, dept b
WHERE a.deptno = b.deptno
AND upper(a.ename) = upper(a.ename)
RETURN deptname;
EXCEPTION
WHEN NO_DATA_FOUND THEN
raise_application_erro(-20000, '僱員不存在');
END;
由於此函式帶有OUT引數,所以要定義變數接收OUT引數和函式的返回值
SQL> var job varchar2(20)
SQL> var dname varchar2920)
SQL> exec :dname:=getinfo('scott',:job)
SQL> print dname job
(4)帶IN OUT引數
在呼叫函式之前需要通過變數給該種引數傳遞資料
CREATE OR REPLACE FUNCTION result
(num1 NUMBER, num2 IN OUT NUMBER)
RETURN NUMBER
AS
v_result NUMBER(6);
v_remain NUMBER;
BEGIN
v_result:=num1/num2;
v_remain:=MOD(num1, num2);
num2 := v_remain;
RETURN v_result;
EXCEPTION
WHEN ZERO_DIVIDE THEN
raise_application_error(-20000, '不能除0');
END;
執行如下:
SQL> var result1 NUMBER
SQL> var result2 NUMBER
SQL> exec :result2:=30
SQL> exec :result1:=result(100, :result2)
SQL> print result1 result2
(5)函式的刪除
DROP FUNCTION 函式名

三.子程式的管理
列出當前使用者的子程式
資料字典檢視USER_OBJECTS顯示當前使用者所包含的所有物件.可以列出使用者的表,檢視,索引,也可以列出使用者的過程,函式等.
SELECT object_name, created, status FROM user_object2 WHERE object_type IN ('PROCEDURE', 'FUNCTION');