子程序可以帶有參數,參數可以具有不同的模式,可以按值傳遞,也可以通過引用傳遞。
形參與實參
形式參數:子定義子程序時,在定義語句中定義的參數稱爲形式參數,簡稱形參。形參的數據類型不包含任何的長度約束。通常使用p開頭作爲形參的前綴,如p_deptno
。
實際參數:在調用子程序時,傳入的具體參數值稱爲實際參數,簡稱實參。實參和它對應的形參必須類型兼容。
參數模式
形參的模式用來控制形參的行爲,有3中模式:IN,OUT,IN OUT。如果沒有指定,默認爲IN。
IN模式的參數稱爲輸入參數,它就像常量一樣,不能被賦值。
OUT模式的參數稱爲輸出參數,輸出參數將會改變參數的值,因此實參不能用固定字符串或常量來傳遞,必須是一個變量。
OUT模式的形參會被初始化爲NULL,所以形參的數據類型是不能有NOT NULL約束的。
IN OUT模式又稱爲輸入/輸出參數,形參可以被讀出和寫入。他的實參也必須是一個變量,不可以是常量或表達式。如果成功地退出子程序,PL/SQL就會爲實參賦值,如果有未捕獲的異常發生,PL/SQL就不會爲實參賦值。
形參的約束
在子程序定義時,形參不能指定長度的約束,任何指定長度或精度的約束都是不合法的。如:
CREATE OR REPLACE PROCEDURE calcSalary(
p_job IN VARCHAR2(10),
p_salary IN OUT NUMBER(10,2))
AS
BEGIN
...
END;
這樣是錯誤的,PL/SQL引擎將拋出編譯時錯誤,必須要去掉對形參中的長度約束。
實際上形參的約束來自於實參,傳入的實參具有怎樣的長度約束,形參就具有怎樣的長度約束。
雖然形參不能用約束聲明,但是可以使用%TYPE對其進行約束。如果形參使用了%TYPE進行聲明,那麼其潛在類型是收到約束的。
參數傳遞方式
有兩種向子程序傳遞參數的方式:一種是前面見過的按位置傳遞,另一種是按名稱傳遞。
大多參數傳遞的場合都是用按位置傳遞方式,只要傳入的實參的位置匹配形參的位置定義即可。如:
calcSalary(v_job,v_sal);
按名稱傳遞是使用=>
作爲關聯的操作符,如:
calcSalary(p_job=>v_job,p_salary=>v_sal);
由於使用了名字進行標識,因此參數的位置就不重要了,這樣的寫法和上面實際上是一樣的:
calcSalary(p_salary=>v_sal,p_job=>v_job);
還可以混合使用按位置傳遞和按名稱傳遞,但是在這種情況下,位置標識法必須在名稱標識法之前。
參數默認值
在定義子程序時,可以使用 DEFAULT關鍵字或賦值語句爲IN模式的參數指定默認值。
CREATE OR REPLACE PROCEDURE newdeptwithdefault (
p_deptno dept.deptno%TYPE DEFAULT 57, --部門編號
p_dname dept.dname%TYPE:='管理部', --部門名稱
p_loc dept.loc%TYPE DEFAULT '江蘇' --位置
)
AS
BEGIN
...
END;
BEGIN
newdeptwithdefault; --不指定任何參數,將使用形參默認值
END;
BEGIN
newdeptwithdefault(58,'事務組'); --p_loc使用默認值
END;
BEGIN
newdeptwithdefault(p_deptno=>58, p_loc=>'南海'); --p_dname使用默認值
END;
使用NOCOPY編譯提示
首先需要理解引用傳遞和值傳遞之間的區別。
值傳遞:當參數通過值傳遞時,參數將從實際參數中被複制到形式參數中。
引用傳遞:實際參數的指針被傳遞到了相應的形式參數中。
默認情況下,PL/SQL通過引用來傳遞IN參數,引用傳遞速度快,因爲僅實際參數的指針傳遞到相應的形式參數中,不需要進行復制,這對於佔用空間較大的參數,比如集合類型具有較高的效率。而IN OUT參數和OUT參數通過值進行傳遞,這主要是因爲對實際參數的約束可以被校驗,當子程序正常結束後,被賦到OUT和IN OUT形參上的值就會複製到對應的實參上。
在使用OUT和IN OUT參數時,如果參數是大型數據結構,比如集合、記錄、對象實例,可以使用NOCOPY編譯提示按引用進行傳遞:
parameter_name [mode] NOCOPY datatype
如:
CREATE OR REPLACE PROCEDURE NoCopyDemo
(
p_InParam IN NUMBER,
p_InOutParam IN OUT NOCOPY VARCHAR2,
p_OutParam OUT NOCOPY VARCHAR2
)
IS
...