sql包體
1. Oracle PL/SQL添加調試信息後,部分包體失效
如果你的所有包的語法是正確的,那麼再調用的時候,系統會自動編譯的,也就是說你不用關注這個問題。
但是如果你有的包語法有問題,那麼及必須一個一個按照被調用的最末層到調用的關系,進行編譯,檢查錯誤。
2. SQl資料庫中包是什麼
一、什麼是PL/SQL包
包就是一個把各種邏輯相關的類型、常量、變數、異常和子程序組合在一起的模式對象。包通常由兩個部分組成:包說明和包體,但有時包體是不需要的。說明(簡寫為spec)是應用程序介面;它聲明了可用的類型、變數、常量、異常、游標和子程序,包體部分完全定義游標和子程序,並對說明中的內容加以實現。
如下例所示,我們可以認為說明部分是一個可選介面,而包體是一個"黑盒"。我們可以調試、增強或替換一個包體而不同改變介面(包說明)。
我們可以從SQL*Plus中使用CREATE PACKAGE語句來創建一個包。語法如下:
CREATE [OR REPLACE] PACKAGE package_name
[AUTHID {CURRENT_USER | DEFINER}]
{IS | AS}
[PRAGMA SERIALLY_REUSABLE;]
[collection_type_definition ...]
[record_type_definition ...]
[subtype_definition ...]
[collection_declaration ...]
[constant_declaration ...]
[exception_declaration ...]
[object_declaration ...]
[record_declaration ...]
[variable_declaration ...]
[cursor_spec ...]
[function_spec ...]
[procere_spec ...]
[call_spec ...]
[PRAGMA RESTRICT_REFERENCES(assertions) ...]
END [package_name];
[CREATE [OR REPLACE] PACKAGE BODY package_name {IS | AS}
[PRAGMA SERIALLY_REUSABLE;]
[collection_type_definition ...]
[record_type_definition ...]
[subtype_definition ...]
[collection_declaration ...]
[constant_declaration ...]
[exception_declaration ...]
[object_declaration ...]
[record_declaration ...]
[variable_declaration ...]
[cursor_body ...]
[function_spec ...]
[procere_spec ...]
[call_spec ...]
[BEGIN
sequence_of_statements]
END [package_name];]
在說明部分聲明的內容都是公有的,對應用程序是可見的。我們必須在所有的其他內容(除了用於為一個特殊的函數命名的編譯指示;這樣的編譯指示必須跟在函數說明之後)聲明之後才可以聲明子程序。
包體中的內容有私有的,它實現了說明部分定義的細節內容,並且對應用程序是不可見的。緊跟著包體聲明部分的是一個可選的初始化部分,它用於初始化包中的變數等。
AUTHID語句決定了是否是所有的打包子程序都按定義者許可權(默認)或調用者許可權執行,其中涉及到的模式對象是在定義者的模式中解析還是在調用者的模式中解析。
一個調用說明能讓我們在Oracle數據詞典中發布一個Java方法或外部C函數。調用說明靠把程序的名稱、參數類型和返回類型映射到它們的SQL副本(SQL counterpart)中來發布程序。
1、PL/SQL包舉例
在下面的例子中,我們把一個記錄類型、游標和兩個employment過程進行打包。要注意,過程hire_employee使用資料庫序列empno_seq和函數SYSDATE分別插入到欄位雇員編號和僱傭日期。
CREATE OR REPLACE PACKAGE emp_actions AS -- spec
TYPE emprectyp IS RECORD(
emp_id INT,
salary REAL
);
CURSOR desc_salary RETURN emprectyp;
PROCEDURE hire_employee(
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER
);
PROCEDURE fire_employee(emp_id NUMBER);
END emp_actions;
CREATE OR REPLACE PACKAGE BODY emp_actions AS -- body
CURSOR desc_salary RETURN emprectyp IS
SELECT empno, sal
FROM emp
ORDER BY sal DESC;
PROCEDURE hire_employee(
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER
) IS
BEGIN
INSERT INTO emp
VALUES (empno_seq.NEXTVAL,
ename,
job,
mgr,
SYSDATE,
sal,
comm,
deptno);
END hire_employee;
PROCEDURE fire_employee(emp_id NUMBER) IS
BEGIN
DELETE FROM emp
WHERE empno = emp_id;
END fire_employee;
END emp_actions;
只有在包說明部分的聲明內容對應用程序才是可見可訪問的;包體的詳細實現是不可見不可訪問的。所以,我們可以在不重新編譯調用程序的前提下修改包體(實現)。
二、PL/SQL包的優點
包提供了幾個優點:模塊化、方便應用程序設計、信息隱藏、附加功能和良好的性能。
模塊化
包能讓我們把邏輯相關的類型、常量、變數、異常和子程序等放到一個命名的PL/SQL模塊中。每一個包都容易理解,包與包之間介面簡單、清晰。這將有助於程序開發。
輕松的程序設計
設計應用程序時,我們首先要確定的是包說明中的介面信息。我們可以在沒有包體的條件下編寫並編譯說明部分。然後引用該包的存儲子程序也會被編譯。在完成整個應用程序之前,我們是不需要完全實現包體部分的。
信息隱藏
有了包,我們就可以指定哪些類型、常量、變數、異常和子程序等是公有(可見和可訪問)或私有(隱藏和不可訪問)。例如,如果一個包里包含了四個子程序,其中三個是公有的一個是私有的。包就會隱藏私有子程序的實現,這樣的話,如果實現內容發生改變,受到影響的只有包本身(不是我們的應用程序)。同樣,對用戶隱藏實現細節也能保證包的完整性。
附加功能
打包公有變數和游標在一個會話期會一直存在。所以,它們可以被當前環境下的所有子程序共享。並且它們允許我們跨事務來維護數據而不用把它保存在資料庫中。
良好的性能
在我們首次調用打包子程序時,整個包就會被載入到內存中。所以,以後調用包中的相關子程序時,就不需要再次讀取磁碟了。包能阻塞級聯依賴,這樣就能避免不必要的編譯。例如,如果我們改變打包函數的實現,Oracle不需要重新編譯調用子程序,因為它們並不依賴於包體。
三、理解包說明
包說明包括了公有聲明。這些聲明的作用於對於資料庫模式來說是本地的,對於包來說是全局的。所以,被聲明的內容可以從應用程序中和包的任何地方訪問。下圖演示了包的作用范圍:
說明中列出了包中對應用程序所有可用的資源。例如,下面的聲明演示了一個接受INTEGER類型的參數並返回一個INTEGER結果的函數fac:
FUNCTION fac (n INTEGER) RETURN INTEGER; -- returns n!
這些就是我們要調用的函數的所有信息。我們並不需要考慮它的實現細節(如,是使用迭代還是遞歸)。
只有子程序和游標有實現部分。所以,如果一個說明只有類型、常量、變數、異常的聲明和調用說明,那麼包體就沒有必要的了。下面就是一個沒有包體的包:
CREATE PACKAGE trans_data AS -- bodiless package
TYPE timerec IS RECORD(
minutes SMALLINT,
hours SMALLINT
);
TYPE transrec IS RECORD(
CATEGORY VARCHAR2,
ACCOUNT INT,
amount REAL,
time_of timerec
);
minimum_balance CONSTANT REAL := 10.00;
number_processed INT;
insufficient_funds EXCEPTION;
END trans_data;
包trans_data不需要包體,因為類型、常量、變數和異常並沒有實現部分。這樣的包能讓我們定義全局變數,可供子程序和資料庫觸發器使用。
1、引用包的內容
如果要引用包內聲明的類型、常量、變數、異常和子程序等,就得使用點標識:
package_name.type_name
package_name.item_name
package_name.subprogram_name
package_name.call_spec_name
我們可以從資料庫觸發器、存儲子程序、3GL(第三代程序語言)應用程序和各種Oracle工具中引用包中的內容。例如,我們可以從SQL*Plus中調用過程hire_employee:
SQL> CALL emp_actions.hire_employee('TATE', 'CLERK', ...);
下例中,我們可以從一個嵌入到Pro*C的匿名PL/SQL塊調用同樣的過程。實參emp_name和job_title是主變數(即聲明在主環境中的變數)。
EXEC SQL EXECUTE
BEGIN
emp_actions.hire_employee(:emp_name, :job_title, ...);
約束
我們不能直接或間接地引用遠程打包變數。例如,我們不能遠程調用下面的過程,因為它在參數初始化子句中引用了打包變數:
CREATE PACKAGE random AS
seed NUMBER;
PROCEDURE initialize (starter IN NUMBER := seed, ...);
同樣,我們也不能在包的內部引用主變數。
^ ^希望對你有幫助