子程序簡介
一般來說,過程和函數被稱爲子程序。過程是一段不具有返回值的代碼塊,而函數會返回一個值。子程序與匿名塊的最大不同是它可以存儲到數據庫的數據字典中,以便重用。
過程一旦被創建,就以編譯的形式被存儲在數據庫中,這樣就可以從別的PL/SQL命名塊或是匿名塊中調用了。
子程序的優點
子程序被創建後,就可以在user_object
數據字典中查詢:
SELECT object_type 對象類型, object_name 對象名稱, status 狀態
FROM user_objects
WHERE object_type IN ('PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'PROCEDURE')
ORDER BY object_type, status, object_name;
除了可重用以外,子程序還有如下優點:
- 提供模塊化的功能。
- 更強的可維護性。
- 更強的可讀性。
- 更強的穩定性。
創建過程
基本語法如下:
[CREATE [OR REPLACEC]]
PROCEDURE procedure_name[(parameter[,parameter]...)]
[AUTHID {DEFINER | CURRENT_USER}]{IS | AS}
[PRAGMA AUTONOMOUS_TRANSACTION;]
[local declarations]
BEGIN
executable statements
[EXCEPTION
exception handlers]
END [name];
- 可選的CREATE語句表示將在數據字典中創建一個獨立的過程,可選的OR REPLACE表示創建時將替換現有的過程定義。通常使用OR REPLACE子句,以便在創建之後進行修改時可以直接替換掉原有的過程。
- PROCEDURE表示要創建一個過程。
- parameter用來指定參數。
- AUTHID子句決定了存儲過程是按所有者權限(默認)調用還是按當前用戶權限執行,也能決定在沒有限定修飾詞的情況下,對所引用的對象是按所有者模式進行解析還是按當前用戶模式進行解析。可以指定CURRENT_USER來覆蓋掉程序的默認行爲。
- 編譯指示
AUTONOMOUS_TRANSACTION
會告訴PL/SQL編譯器把過程標記爲自治。自治事務能讓我們把主事務掛起,執行SQL操作,提交或回滾自治事務,然後再恢復主事務。 - IS或AS之後的語句稱爲過程體,local declarations是局部變量定義區,可以定義任意的類型、變量、常量、異常等。在這裏定義只具有本地作用域,當過程退出時所有的定義將被釋放。
- BEGIN到END之間的語句是標準的PL/SQL語句塊。
看一個例子:
CREATE OR REPLACE PROCEDURE newdept (
p_deptno IN NUMBER, --部門編號
p_dname IN VARCHAR2, --部門名稱
p_loc IN VARCHAR2 --位置
)
AS
v_deptcount NUMBER(4); --保存是否存在部門編號
e_duplication_dept EXCEPTION;
BEGIN
SELECT COUNT (*) INTO v_deptcount FROM dept
WHERE deptno = p_deptno; --查詢在dept表中是否存在部門編號
IF v_deptcount > 0 --如果存在相同的部門記錄
THEN --拋出異常
RAISE e_duplication_dept;
END IF;
INSERT INTO dept(deptno, dname, loc)
VALUES (p_deptno, p_dname, p_loc);--插入記錄
COMMIT; --提交事務
EXCEPTION
WHEN e_duplication_dept THEN
ROLLBACK;
raise_application_error (-20002, '出現了相同的員工記錄');
END;
創建函數
語法如下:
[CREATE [OR REPLACE]]
FUNCTION funciton_nme[(parameter[,parameter]...)] RETURN datatype
[AUTHID {DEFINER | CURRENT_USER}]
[PRAGMA AUTONOMOUS_TRANSACTION;]
[local declarations]
BEGIN
executable statements
[EXCEPTION
exception handlers]
END [name];
函數與過程基本相似,一個很重要的不同點是函數具有RETURN子句,指定函數的返回類型。
看一個例子:
CREATE OR REPLACE FUNCTION getraisedsalary (p_empno emp.empno%TYPE)
RETURN NUMBER
IS
v_job emp.job%TYPE; --職位變量
v_sal emp.sal%TYPE; --薪資變量
v_salaryratio NUMBER (10, 2); --調薪比率
BEGIN
--獲取員工表中的薪資信息
SELECT job, sal INTO v_job, v_sal FROM emp WHERE empno = p_empno;
CASE v_job --根據不同的職位獲取調薪比率
WHEN '職員' THEN
v_salaryratio := 1.09;
WHEN '銷售人員' THEN
v_salaryratio := 1.11;
WHEN '經理' THEN
v_salaryratio := 1.18;
ELSE
v_salaryratio := 1;
END CASE;
IF v_salaryratio <> 1 --如果有調薪的可能
THEN
RETURN ROUND(v_sal * v_salaryratio,2); --返回調薪後的薪資
ELSE
RETURN v_sal; --否則不返回薪資
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0; --如果沒找到原工記錄,返回0
END;
RETURN語句
在過程或函數中都可以使用RETURN,但是有明顯的區別:
- 過程中RETURN不返回值,它的作用是立即退出過程的執行,將控制權返回給過程的調用者。
- 函數中RETURN必須包含一個表達式,表達式的值會在RETURN語句執行時被計算,然後賦給在聲明中的RETURN語句中指定的數據類型的變量,也就是函數標識符,再將控制權返回給調用者。
查看數據字典中的子程序信息
如果想查看已經創建的子程序或Oracle內置的子程序信息,可以通過如下3個視圖進行查詢:
- user_objects
:包含當前登錄用戶的所有對象的信息,比如對象的名稱、創建的時間、最後被修改的時間、對象類型、對象的有效性狀態等。
- user_source
:包含當前登錄用戶所擁有的對象的源代碼,比如名稱、類型、描述等信息。
- user_errors
:包含當前登錄用戶當前所發生的錯誤信息,比如對象名稱、類型、序列、發生錯誤的位置、文本等。使用這個視圖可以輕鬆地知道當前編譯的錯誤消息,誰用誰知道。
刪除子程序
可以使用DROP FUNCTION function_name
和DROP PROCEDURE procedure_name
來刪除函數和過程。要注意,刪除者應該是函數或過程的創建者或擁有DROP ANY PROCEDURE系統權限的人。
DROP命令是一個DDL語句,隱式地帶有一個COMMIT命令,因此一旦刪除,就從數據庫中永遠移除了。一般我們使用CREATE OR REPLAE來重新編譯和修改一個子程序。