Oracle PL/SQL進階編程(第二彈:子程序參數)

子程序可以帶有參數,參數可以具有不同的模式,可以按值傳遞,也可以通過引用傳遞。

形參與實參

形式參數:子定義子程序時,在定義語句中定義的參數稱爲形式參數,簡稱形參。形參的數據類型不包含任何的長度約束。通常使用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
...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章