plsql 程式包的建立與應用
本篇主要內容如下:
7.1 程式包簡介
程式包(PACKAGE,簡稱包)是一組相關過程、函式、變數、常量和遊標等PL/SQL程式設計元素的組合,作為一個完整的單元儲存在資料庫中,用名稱來標識包.
與高階語言中的類相同,包中的程式元素也分為公用元素和私用元素兩種,這兩種元素的區別是他們允許訪問的程式範圍不同,即它們的作用域不同。公用元素不僅可以被包中的函式、過程所呼叫,也可以被包外的PL/SQL程式訪問,而私有元素只能被包內的函式和過程式所訪問。
當然,對於不包含在程式包中的過程、函式是獨立存在的。一般是先編寫獨立的過程與函式,待其較為完善或經過充分驗證無誤後,再按邏輯相關性組織為程式包。
程式包的優點
u 簡化應用程式設計:程式包的說明部分和包體部分可以分別建立各編譯。主要體現 在以下三個方面:
1) 可以在設計一個應用程式時,只建立各編譯程式包的說明部分,然後再編寫引用該程式包的PL/SQL塊。
2) 當完成整個應用程式的整體框架後,再回頭來定義包體部分。只要不改變包的說明部分,就可以單獨除錯、增加或替換包體的內容,這不會影響其他的應用程式。
3) 更新包的說明後必須重新編譯引用包的應用程式,但更新包體,則不需重新編譯引用包的應用程式,以快速進行進行應用程式的原形開發。
u 模組化:可將邏輯相關的PL/SQL塊或元素等組織在一起,用名稱來唯一標識程式包。把一個大的功能模組劃分人適當個數小的功能模組,分別完成各自的功能。這樣組織的程式包都易於編寫,易於理解更易於管理。
u資訊隱藏:因為包中的元素可以分為公有元素和私有元素。公有元素可被程式包內的過程、函式等的訪問,還可以被包外的PL/SQL訪問。但對於私有元素只能被包內的過程、函式等訪問。對於使用者,只需知道包的說明,不用瞭解包休的具體細節。
u 效率高:程式包在應用程式第一次呼叫程式包中的某個元素時,ORACLE將把整個程式包載入到記憶體中,當第二次訪問程式包中的元素時,ORACLE將直接從內在中讀取,而不需要進行磁碟I/O操作而影響速度,同時位於內在中的程式包可被同一會話期間的其它應用程式共享。因此,程式包增加了重用性並改善了多使用者、多應用程式環境的效率。
對程式包的優點可總結如下:在PL/SQL程式設計中,使用包不僅可以使程式設計模組化,對外隱藏包內所使用的資訊(通過使用私用變數),而寫可以提高程式的執行效率。因為,當程式首次呼叫包內函式或過程時,ORACLE將整個包調入記憶體,當再次訪問包內元素時,ORACLE直接從記憶體中讀取,而不需要進行磁碟I/O操作,從而使程式執行效率得到提高。
7.2 程式包的定義
程式包的定義分為程式包說明定義和程式包主體定義兩部分組成。
程式包說明用於宣告包的公用元件,如變數、常量、自定義資料型別、異常、過程、函式、遊標等。包說明中定義的公有元件不僅可以在包內使用,還可以由包外其他過程、函式。但需要說明與注意的是,我們為了實現資訊的隱藏,建議不要將所有元件都放在包說明處宣告,只應把公共元件放在包宣告部分。包的名稱是唯一的,但對於兩個包中的公有元件的名稱可以相同,這種用“包名.公有元件名“加以區分。
包體是包的具體實現細節,其實現在包說明中宣告的所有公有過程、函式、遊標等。當然也可以在包體中宣告僅屬於自己的私有過程、函式、遊標等。建立包體時,有以下幾點需要注意:
u 包體只能在包說明被建立或編譯後才能進行建立或編譯。
u 在包體中實現的過程、函式、遊標的名稱必須與包說明中的過程、函式、遊標一致,包括名稱、引數的名稱以及引數的模式(IN、OUT、IN OUT)。並建設按包說明中的次序定義包體中具體的實現。
u 在包體中宣告的資料型別、變數、常量都是私有的,只能在包體中使用而不能被印刷體外的應用程式訪問與使用。
u 在包體執行部分,可對包說明,包體中宣告的公有或私有變數進行初始化或其它設定。
建立程式包說明語法格式:
CREATE[OR REPLACE] PACKAGE package_name[AUTHID {CURRENT_USER | DEFINER}]
{IS|AS}
[公有資料型別定義[公有資料型別定義]…]
[公有遊標宣告[公有遊標宣告]…]
[公有變數、常量宣告[公有變數、常量宣告]…]
[公有函式宣告[公有函式宣告]…]
[公有過程宣告[公有過程宣告]…]
END[package_name];
其中:AUTHIDCURRENT_USER和AUTHIDDEFINER選項說明應用程式在呼叫函式時所使用的許可權模式,它們與CREATEFUNCTION語句中invoker_right_clause子句的作用相同。
建立程式包主體語法格式:
CREATE[OR REPLACE] PACKAGE BODY package_name{IS|AS}
[私有資料型別定義[私有資料型別定義]…]
[私有變數、常量宣告[私有變數、常量宣告]…]
[私有異常錯誤宣告[私有異常錯誤宣告]…]
[私有函式宣告和定義[私有函式宣告和定義]…]
[私有函過程宣告和定義[私有函過程宣告和定義]…]
[公有遊標定義[公有遊標定義]…]
[公有函式定義[公有函式定義]…]
[公有過程定義[公有過程定義]…]
BEGIN
執行部分(初始化部分)
END package_name;
其中:在包主體定義公有程式時,它們必須與包定義中所宣告子程式的格式完全一致。
7.3 包的開發步驟
與開發儲存過程類似,包的開發需要幾個步驟:
1. 將每個儲存過程調式正確;
2. 用文字編輯軟體將各個儲存過程和函式整合在一起;
3. 按照包的定義要求將整合的文字的前面加上包定義;
4. 按照包的定義要求將整合的文字的前面加上包主體;
5. 使用SQLPLUS或開發工具進行調式。
7.4 包定義的說明
例1:建立的包為DEMO_PKG,該包中包含一個記錄變數DEPTREC、兩個函式和一個過程。實現對dept表的增加、刪除與查詢。
CREATE OR REPLACE PACKAGE DEMO_PKG
IS
DEPTREC DEPT%ROWTYPE;
—Add dept…
FUNCTION add_dept(
dept_no NUMBER,
dept_name VARCHAR2,
location VARCHAR2)
RETURN NUMBER;
—delete dept…
FUNCTION delete_dept(dept_no NUMBER)
RETURN NUMBER;
—query dept…
PROCEDURE query_dept(dept_no IN NUMBER);
END DEMO_PKG;
包主體的建立方法,它實現上面所宣告的包定義,並在包主體中宣告一個私有變數flag
和一個私有函式check_dept,由於在add_dept和remove_dept等函式中需要呼叫check_dpet函式,
所以,在定義check_dept 函式之前首先對該函式進行宣告,這種宣告方法稱作前向宣告。
CREATE OR REPLACE PACKAGE BODY DEMO_PKG
IS
FUNCTION add_dept
(
dept_no NUMBER,
dept_name VARCHAR2,
location VARCHAR2
)
RETURN NUMBER
IS
empno_remaining EXCEPTION; —自定義異常
PRAGMA EXCEPTION_INIT(empno_remaining, –1);
/* -1 是違反唯一約束條件的錯誤程式碼 */
BEGIN
INSERT INTO dept VALUES(dept_no, dept_name, location);
IF SQL%FOUND THEN
RETURN 1;
END IF;
EXCEPTION
WHEN empno_remaining THEN
RETURN 0;
WHEN OTHERS THEN
RETURN –1;
END add_dept;
FUNCTION delete_dept(dept_no NUMBER)
RETURN NUMBER
IS
BEGIN
DELETE FROM dept WHERE deptno = dept_no;
IF SQL%FOUND THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN –1;
END delete_dept;
PROCEDURE query_dept
(dept_no IN NUMBER)
IS
BEGIN
SELECT * INTO DeptRec FROM dept WHERE deptno=dept_no;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:資料庫中沒有編碼為‘||dept_no||‘的部門‘);
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE(‘程式執行錯誤,請使用遊標進行操作!‘);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||‘—-‘||SQLERRM);
END query_dept;
BEGIN
Null;
END DEMO_PKG;
對包內共有元素的呼叫格式為:包名.元素名稱
呼叫DEMO_PKG包內函式對dept表進行插入、查詢和刪除操作,並通過DEMO_PKG包中的
記錄變數DEPTREC顯示所查詢到的資料庫資訊:
DECLARE
Var NUMBER;
BEGIN
Var := DEMO_PKG.add_dept(90,‘HKLORB‘, ‘HAIKOU‘);
IF var =-1 THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||‘—-‘||SQLERRM);
ELSIF var =0 THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:該部門記錄已經存在!‘);
ELSE
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:新增記錄成功!‘);
DEMO_PKG.query_dept(90);
DBMS_OUTPUT.PUT_LINE(DEMO_PKG.DeptRec.deptno||‘—‘||
DEMO_PKG.DeptRec.dname||‘—‘||DEMO_PKG.DeptRec.loc);
var := DEMO_PKG.delete_dept(90);
IF var =-1 THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||‘—-‘||SQLERRM);
ELSIF var=0 THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:該部門記錄不存在!‘);
ELSE
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:刪除記錄成功!‘);
END IF;
END IF;
END;
例2: 建立包EMP_PKG,讀取emp表中的資料
—建立包說明
CREATE OR REPLACE PACKAGE EMP_PKG
IS
TYPE emp_table_type IS TABLE OF emp%ROWTYPE
INDEX BY BINARY_INTEGER;
PROCEDURE read_emp_table (p_emp_table OUT emp_table_type);
END EMP_PKG;
—建立包體
CREATE OR REPLACE PACKAGE BODY EMP_PKG
IS
PROCEDURE read_emp_table (p_emp_table OUT emp_table_type)
IS
I BINARY_INTEGER := 0;
BEGIN
FOR emp_record IN ( SELECT * FROM emp ) LOOP
P_emp_table(i) := emp_record;
I := I + 1;
END LOOP;
END read_emp_table;
END EMP_PKG;
—執行
DECLARE
E_table EMP_PKG.emp_table_type;
BEGIN
EMP_PKG.read_emp_table(e_table);
FOR I IN e_table.FIRST ..e_table.LAST LOOP
DBMS_OUTPUT.PUT_LINE(e_table(i).empno||‘ ‘||e_table(i).ename);
END LOOP;
END;
例3: 建立包MANAGE_EMP_PKG,對員工進行管理(新增員工、新增部門、刪除指定員工、刪除指定部門、增加指定員工的工資與獎金):
—建立序列從100開始,依次增加1
CREATE SEQUENCE empseq
START WITH 100
INCREMENT BY 1
ORDER NOCYCLE;
—建立序列從100開始,依次增加10
CREATE SEQUENCE deptseq
START WITH 100
INCREMENT BY 10
ORDER NOCYCLE;
— *******************************************
— 建立包說明
— 包 名:MANAGE_EMP_PKG
— 功能描述:對員工進行管理(新增員工,新增部門
— ,刪除員工,刪除部門,增加工資與獎金等)
— 建立人員:胡勇
— 建立日期:2010-05-19
— Q Q: 80368704
— E-mail : [email protected]
— WebSite: http://www.cnblogs.com/huyong
— ***********************************
CREATE OR REPLACE PACKAGE MANAGE_EMP_PKG
AS
—增加一名員工
FUNCTION hire_emp
(ename VARCHAR2, job VARCHAR2
, mgr NUMBER, sal NUMBER
, comm NUMBER, deptno NUMBER)
RETURN NUMBER;
—新增一個部門
FUNCTION add_dept(dname VARCHAR2, loc VARCHAR2)
RETURN NUMBER;
—刪除指定員工
PROCEDURE remove_emp(empno NUMBER);
—刪除指定部門
PROCEDURE remove_dept(deptno NUMBER);
—增加指定員工的工資
PROCEDURE increase_sal(empno NUMBER, sal_incr NUMBER);
—增加指定員工的獎金
PROCEDURE increase_comm(empno NUMBER, comm_incr NUMBER);
END MANAGE_EMP_PKG;—建立包說明結束
— *******************************************
— 建立包體
— 包 名:MANAGE_EMP_PKG
— 功能描述:對員工進行管理(新增員工,新增部門
— ,刪除員工,刪除部門,增加工資與獎金等)
— 建立人員:胡勇
— 建立日期:2010-05-19
— Q Q: 80368704
— E-mail : [email protected]
— WebSite: http://www.cnblogs.com/huyong
— ***********************************
CREATE OR REPLACE PACKAGE BODY MANAGE_EMP_PKG
AS
total_emps NUMBER; —員工數
total_depts NUMBER; —部門數
no_sal EXCEPTION;
no_comm EXCEPTION;
—增加一名員工
FUNCTION hire_emp(ename VARCHAR2, job VARCHAR2, mgr NUMBER,
sal NUMBER, comm NUMBER, deptno NUMBER)
RETURN NUMBER —返回新增加的員工編號
IS
new_empno NUMBER(4);
BEGIN
SELECT empseq.NEXTVAL INTO new_empno FROM dual;
SELECT COUNT(*) INTO total_emps FROM emp;—當前記錄總數
INSERT INTO emp
VALUES (new_empno, ename, job, mgr, sysdate, sal, comm, deptno);
total_emps:=total_emps+1;
RETURN(new_empno);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:發生系統錯誤!‘);
END hire_emp;
—新增一個部門
FUNCTION add_dept(dname VARCHAR2, loc VARCHAR2)
RETURN NUMBER
IS
new_deptno NUMBER(4); —部門編號
BEGIN
—得到一個新的自增的員工編號
SELECT deptseq.NEXTVAL INTO new_deptno FROM dual;
SELECT COUNT(*) INTO total_depts FROM dept;—當前部門總數
INSERT INTO dept VALUES (new_deptno, dname, loc);
total_depts:=total_depts;
RETURN(new_deptno);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:發生系統錯誤!‘);
END add_dept;
—刪除指定員工
PROCEDURE remove_emp(empno NUMBER)
IS
no_result EXCEPTION; —自定義異常
BEGIN
DELETE FROM emp WHERE emp.empno=remove_emp.empno;
IF SQL%NOTFOUND THEN
RAISE no_result;
END IF;
total_emps:=total_emps – 1; —總的員工數減1
EXCEPTION
WHEN no_result THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:你需要的資料不存在!‘);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:發生系統錯誤!‘);
END remove_emp;
—刪除指定部門
PROCEDURE remove_dept(deptno NUMBER)
IS
no_result EXCEPTION; —自定義異常
exception_deptno_remaining EXCEPTION; —自定義異常
/*-2292 是違反一致性約束的錯誤程式碼*/
PRAGMA EXCEPTION_INIT(exception_deptno_remaining, –2292);
BEGIN
DELETE FROM dept WHERE dept.deptno=remove_dept.deptno;
IF SQL%NOTFOUND THEN
RAISE no_result;
END IF;
total_depts:=total_depts–1; —總的部門數減1
EXCEPTION
WHEN no_result THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:你需要的資料不存在!‘);
WHEN exception_deptno_remaining THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:違反資料完整性約束!‘);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:發生系統錯誤!‘);
END remove_dept;
—給指定員工增加指定數量的工資
PROCEDURE increase_sal(empno NUMBER, sal_incr NUMBER)
IS
curr_sal NUMBER(7, 2); —當前工資
BEGIN
—得到當前工資
SELECT sal INTO curr_sal FROM emp WHERE emp.empno=increase_sal.empno;
IF curr_sal IS NULL THEN
RAISE no_sal;
ELSE
UPDATE emp SET sal = sal + increase_sal.sal_incr —當前工資加新增的工資
WHERE emp.empno = increase_sal.empno;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:你需要的資料不存在!‘);
WHEN no_sal THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:此員工的工資不存在!‘);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:發生系統錯誤!‘);
END increase_sal;
—給指定員工增加指定數量的獎金
PROCEDURE increase_comm(empno NUMBER, comm_incr NUMBER)
IS
curr_comm NUMBER(7,2);
BEGIN
—得到指定員工的當前資金
SELECT comm INTO curr_comm
FROM emp WHERE emp.empno = increase_comm.empno;
IF curr_comm IS NULL THEN
RAISE no_comm;
ELSE
UPDATE emp SET comm = comm + increase_comm.comm_incr
WHERE emp.empno=increase_comm.empno;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:你需要的資料不存在!‘);
WHEN no_comm THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:此員工的獎金不存在!‘);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘溫馨提示:發生系統錯誤!‘);
END increase_comm;
END MANAGE_EMP_PKG;—建立包體結束
—呼叫
SQL> variable empno number
SQL>execute :empno:= manage_emp_pkg.hire_emp(‘HUYONG‘,PM,1455,5500,14,10)
PL/SQL procedure successfully completed
empno
———-
105
例4:利用遊標變數建立包 CURROR_VARIBAL_PKG。由於遊標變數指是一個指標,其狀態是不確定的,
因此它不能隨同包儲存在資料庫中,既不能在PL/SQL包中宣告遊標變數。
但在包中可以建立遊標變數參照型別,並可向包中的子程式傳遞遊標變數引數。
— **************************************
— 建立包體
— 包 名:CURROR_VARIBAL_PKG
— 功能描述:在包中引用遊標變數
— 建立人員:胡勇
— 建立日期:2010-05-19
— Q Q: 80368704
— E-mail : [email protected]
— WebSite: http://www.cnblogs.com/huyong
— **************************************
CREATE OR REPLACE PACKAGE CURROR_VARIBAL_PKG AS
TYPE DeptCurType IS REF CURSOR
RETURN dept%ROWTYPE; —強型別定義
TYPE CurType IS REF CURSOR;— 弱型別定義
PROCEDURE OpenDeptVar(
Cv IN OUT DeptCurType,
Choice INTEGER DEFAULT 0,
Dept_no NUMBER DEFAULT 50,
Dept_name VARCHAR DEFAULT ‘%‘);
END;
— **************************************
— 建立包體
— 包 名:CURROR_VARIBAL_PKG
— 功能描述:在包中引用遊標變數
— 建立人員:胡勇
— 建立日期:2010-05-19
— Q Q: 80368704
— E-mail : [email protected]
— WebSite: http://www.cnblogs.com/huyong
— **************************************
CREATE OR REPLACE PACKAGE BODY CURROR_VARIBAL_PKG
AS
PROCEDURE OpenDeptvar(
Cv IN OUT DeptCurType,
Choice INTEGER DEFAULT 0,
Dept_no NUMBER DEFAULT 50,
Dept_name VARCHAR DEFAULT ‘%’)
IS
BEGIN
IF choice =1 THEN
OPEN cv FOR SELECT * FROM dept WHERE deptno <= dept_no;
ELSIF choice = 2 THEN
OPEN cv FOR SELECT * FROM dept WHERE dname LIKE dept_name;
ELSE
OPEN cv FOR SELECT * FROM dept;
END IF;
END OpenDeptvar;
END CURROR_VARIBAL_PKG;
—定義一個過程
CREATE OR REPLACE PROCEDURE UP_OpenCurType(
Cv IN OUT CURROR_VARIBAL_PKG.CurType,
FirstCapInTableName CHAR)
AS
BEGIN
—CURROR_VARIBAL_PKG.CurType採用弱型別定義
—所以可以使用它定義的遊標變數開啟不同型別的查詢語句
IF FirstCapInTableName = ‘D‘ THEN
OPEN cv FOR SELECT * FROM dept;
ELSE
OPEN cv FOR SELECT * FROM emp;
END IF;
END UP_OpenCurType;
—定義一個應用
DECLARE
DeptRec Dept%ROWTYPE;
EmpRec Emp%ROWTYPE;
Cv1 CURROR_VARIBAL_PKG.deptcurtype;
Cv2 CURROR_VARIBAL_PKG.curtype;
BEGIN
DBMS_OUTPUT.PUT_LINE(‘遊標變數強型別定義應用‘);
CURROR_VARIBAL_PKG.OpenDeptVar(cv1, 1, 30);
FETCH cv1 INTO DeptRec;
WHILE cv1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(DeptRec.deptno||‘:‘||DeptRec.dname);
FETCH cv1 INTO DeptRec;
END LOOP;
CLOSE cv1;
DBMS_OUTPUT.PUT_LINE(‘遊標變數弱型別定義應用‘);
CURROR_VARIBAL_PKG.OpenDeptvar(cv2, 2, dept_name => ‘A%‘);
FETCH cv2 INTO DeptRec;
WHILE cv2%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(DeptRec.deptno||‘:‘||DeptRec.dname);
FETCH cv2 INTO DeptRec;
END LOOP;
DBMS_OUTPUT.PUT_LINE(‘遊標變數弱型別定義應用—dept表‘);
UP_OpenCurType(cv2, ‘D‘);
FETCH cv2 INTO DeptRec;
WHILE cv2%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(deptrec.deptno||‘:‘||deptrec.dname);
FETCH cv2 INTO deptrec;
END LOOP;
DBMS_OUTPUT.PUT_LINE(‘遊標變數弱型別定義應用—emp表‘);
UP_OpenCurType(cv2, ‘E‘);
FETCH cv2 INTO EmpRec;
WHILE cv2%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(emprec.empno||‘:‘||emprec.ename);
FETCH cv2 INTO emprec;
END LOOP;
CLOSE cv2;
END;
———–執行結果——————-
遊標變數強型別定義應用
10:ACCOUNTING
20:RESEARCH
30:SALES
遊標變數弱型別定義應用
10:ACCOUNTING
遊標變數弱型別定義應用—dept表
10:ACCOUNTING
20:RESEARCH
30:SALES
40:OPERATIONS
50:50abc
60:Developer
遊標變數弱型別定義應用—emp表
7369:SMITH
7499:ALLEN
7521:WARD
7566:JONES
7654:MARTIN
7698:BLAKE
7782:CLARK
7788:SCOTT
7839:KING
7844:TURNER
7876:ADAMS
7900:JAMES
7902:FORD
7934:MILLER
PL/SQL procedure successfully completed
7.5 子程式過載
PL/SQL 允許對包內子程式和本地子程式進行過載。所謂過載時指兩個或多個子程式有相同的名稱,但擁有不同的引數變數、引數順序或引數資料型別。
例5:
— *******************************************
— 建立包說明
— 包 名:DEMO_PKG1
— 功能描述:建立包對子程式過載進行測試
— 建立人員:胡勇
— 建立日期:2010-05-22
— Q Q: 80368704
— E-mail : [email protected]
— WebSite: http://www.cnblogs.com/huyong
— ******************************************
CREATE OR REPLACE PACKAGE DEMO_PKG1
IS
DeptRec dept%ROWTYPE;
V_sqlcode NUMBER;
V_sqlerr VARCHAR2(2048);
—兩個子程式名字相同,但引數型別不同
FUNCTION query_dept(dept_no IN NUMBER)
RETURN INTEGER;
FUNCTION query_dept(dept_no IN VARCHAR2)
RETURN INTEGER;
END DEMO_PKG1;
— *******************************************
— 建立包體
— 包 名:DEMO_PKG1
— 功能描述:建立包對子程式過載進行測試
— 建立人員:胡勇
— 建立日期:2010-05-22
— Q Q: 80368704
— E-mail : [email protected]
— WebSite: http://www.cnblogs.com/huyong
— ******************************************
CREATE OR REPLACE PACKAGE BODY DEMO_PKG1
IS
FUNCTION check_dept(dept_no NUMBER)
RETURN INTEGER
IS
deptCnt INTEGER; —指定部門號的部門數量
BEGIN
SELECT COUNT(*) INTO deptCnt FROM dept WHERE deptno = dept_no;
IF deptCnt > 0 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END check_dept;
FUNCTION check_dept(dept_no VARCHAR2)
RETURN INTEGER
IS
deptCnt INTEGER;
BEGIN
SELECT COUNT(*) INTO deptCnt FROM dept WHERE deptno=dept_no;
IF deptCnt > 0 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END check_dept;
FUNCTION query_dept(dept_no IN NUMBER)
RETURN INTEGER
IS
BEGIN
IF check_dept(dept_no) =1 THEN
SELECT * INTO DeptRec FROM dept WHERE deptno=dept_no;
RETURN 1;
ELSE
RETURN 0;
END IF;
END query_dept;
FUNCTION query_dept(dept_no IN VARCHAR2)
RETURN INTEGER
IS
BEGIN
IF check_dept(dept_no) =1 THEN
SELECT * INTO DeptRec FROM dept WHERE deptno = dept_no;
RETURN 1;
ELSE
RETURN 0;
END IF;
END query_dept;
END DEMO_PKG1;
7.6 加密實用程式
ORACLE 提供了一個實用工具來加密或者包裝使用者的PL/SQL,它會將使用者的PL/SQL改變為只有ORACLE能夠解釋的程式碼版本.
WRAP 實用工具位於$ORACLE_HOME/BIN.
格式為:
WRAP INAME= [ONAME=]
wrap iname=e:\sample.txt
注意:在加密前,請將PL/SQL程式先儲存一份,以備後用。
7.7 刪除包
可以使用 DROP PACKAGE 命令對不需要的包進行刪除,語法如下:
DROP PACKAGE [BODY][user.]package_name;DROPPROCEDURE OpenCurType; —刪除儲存過程
—刪除我們例項中建立的各個包DROP PACKAGE demo_pack;
DROP PACKAGE demo_pack1;
DROP PACKAGE emp_mgmt;
DROP PACKAGE emp_package;
7.8 包的管理
包與過程、函式一樣,也是儲存在資料庫中的,可以隨時檢視其原始碼。若有需要,在建立包時可以隨時檢視更詳細的編譯錯誤。不需要的包也可以刪除。
同樣,為了避免呼叫的失敗,在更新表的結構後,一定要記得重新編譯依賴於它的程式包。在更新了包說明或包體後,也應該重新編譯包說明與包體。語法如下:
ALTER PACKAGE package_name COMPILE [PACKAGE|BODY|SPECIFICATION];也可以通過以下資料字典檢視檢視包的相關。
DBA_SOURCE, USER_SOURCE, USER_ERRORS,DBA–OBJECTS
如,我們可以用:select text from user_source wherename=‘DEMO_PKG1′;來檢視我們建立的包的原始碼。
相關推薦
plsql 程式包的建立與應用
本篇主要內容如下:7.1 程式包簡介 程式包(PACKAGE,簡稱包)是一組相關過程、函式、變數、常量和遊標等PL/SQL程式設計元素的組合,作為一個完整的單元儲存在資料庫中,用名稱來標識包.與高階語言中的類相同,包中的程式元素也分為公用元素和私用元素兩種,這兩種元素
索引與檢視的建立與應用
實驗目的: 1、理解索引和點陣圖索引的基本概念 2、掌握索引和點陣圖索引的建立方法,並使用索引對查詢過程產生的影響進行分析 3、理解檢視的基本概念 4、掌握檢視的建立方法,並對檢視中資料查詢與更新進行操作,明確其使用的注意事項。 實驗步驟:
Unity3D基礎學習之AssetBundle 資源包建立與載入
前幾天做了AssentBundle的例子,遇到了問題,在論壇上問了三天都沒人解答,最後在一個朋友的幫助下解決了。下面介紹AssentBundle。 AssetBundles讓你通過WWW類流式載入額外的資源並在執行時例項化它們。AssetBundles通過BuildPipe
程式包+建立包規範+建立包體+刪除程式包
程式包 1作用是為了實程式模組化 2程式包裡面可以包含儲存過程,函式,變數,遊標等PL/SQL程式 3程式包類似java的jar包,儲存過程,函式,變數,遊標等相當jar包提供的方法 4呼叫程式包裡面的儲存過程,函式等元素時,oracle會把程式包調入記
plsql建立程式包和包體
-- 包頭 create or replace package *** is procedure ***_SP(pi_tlb_id in string ,po_result out string); end ***; -- 包體 create
【轉載】linux作業系統與應用程式的main函式
來源:https://blog.csdn.net/h542723151/article/details/52154871 這幾天一直在糾結: main函式是程式的入口,一個程式啟動後,經過bootloader的初始化就該經main函式進入C語言的世界,但是linux中每個應用程式的開始都是
ROS系列四:建立ROS程式包
轉自:http://wiki.ros.org/cn/ROS/Tutorials/CreatingPackage 目錄 一個catkin程式包由什麼組成? 在catkin工作空間中的程式包 建立一個catkin程式包 程式包依賴關係 一級依賴 間接依賴 自
大資料篇:Spark-shell的測試及Scala獨立應用程式的編寫與sbt打包
一、在 Spark Shell 中執行程式碼 Spark shell 提供了簡單的方式來學習 API,並且提供了互動的方式來分析資料。你可以輸入一條語句,Spark shell會立即執行語句並返回結果,這就是我們所說的REPL(Read-Eval-Print Loop,互動式直譯器
無法安裝程式包“Newtonsoft.Json 6.0.4”。你正在嘗試將此程式包安裝到目標為“.NETFramework,Version=v4.7”的專案中,但該程式包不包含任何與該框架相容的程式集
今天在ConsoleApp裡面安裝SignalR.SelfHost,但是預設的SelfHost安裝的JSON檔案是6.0.4不相容.NET框架,只要手動安裝上JSON,再安裝SignalR.SelfHost的時候,就不會安裝預設的JSON了,也就不會出錯了。 Install-Packa
應用程式測試方法與技巧
今天解決專案問題時,忽然發現做了很多年測試,經常清理快取臨時檔案,刪除修改配置檔案,有時確忽略了這些對測試的影響和作用。 最近困擾較多的是office外掛測試,外掛安裝挑環境,相容性不夠好,導致我們通過頻繁重灌作業系統和重灌office軟體來驗證外掛是否可以正常啟動和載入。 起初自己通過事件管理器來獲取錯
6.2.2-1 【指標與引用】在二叉樹建立的應用
0 引子 本文旨在通過二叉樹的遞迴建立,分析指標與引用,函式形參與實參的具體實現。 二叉樹的遍歷,通常是利用建立好的二叉連結串列的首地址,也即根節點地址。主函式先定義一指標,再通過二叉樹建立函式返回根結點地址,或者將定義的指標作為形參來實現修改。 這就涉及函式形參與實參的呼叫機制。實參賦給形
【ROS】建立工作空間和程式包
要使用ROS系統進行開發,首先需要在ROS下建立工作空間(workspace)和程式包(package)。 建立工作空間: $ mkdir -p ~/catkin_ws/src 執行上述命令即在使用者主目錄下建立了catkin_ws資料夾及其子資料夾src(-p表示建立目標路徑上的所
win32應用程式,TCHAR與CHAR的相互轉換
TCHR 與 CHAR相互轉換 含義 TChar to Char CHAR To TCHAR 含義 TCHAR:在Unicode編碼下,為寬字元wchar;在Ansi編碼下,為字元char。 CHAR:是在Ansi編碼下字串格式。
【Anychart教程】在您的Xamarin應用程式中建立美觀且使用者友好的表單
下載Telerik UI for Asp.Net最新版本 幾乎每個移動應用都有收集使用者輸入的場景。正是考慮到這一點,我們為Xamarin的Telerik UI引入了Entry控制元件,以幫助您建立漂亮且使用者友好的表單。 在Telerik UI中為Xamarin引入新條目 用於Xama
VisualStudioCode中建立多個ASP.NET Core 專案、類庫、控制檯程式,並新增應用間的引用
首先安裝VisualStudioCode並且可以使用。 1、首先建立MyApps資料夾,作為專案主目錄,下面將在這個資料夾中建立多個web應用程式、型別、控制檯程式等。 2、開啟VisualStudioCode軟體,選擇“File”->"Open Folder",在彈出框中選擇上述建立的資料夾“My
解決R/RStudio中安裝包“無法與伺服器建立連線”
這幾天在用RStudio寫程式的時候突然出現無法從網路直接安裝r包的問題,也無法從本地直接安裝。通過多方嘗試找到了問題解決的辦法,現在記錄在這裡。程式報錯如下: > install.packages('REmap') Warning in install.packag
SharePoint建立web應用程式報錯"This page can’t be displayed" 建立site collection報錯
建立web應用程式(web application)的時候,發現一直loading最後顯示”This page can’t be displayed”,當我重新整理頁面的時候發現web application已經建立好了,於是就想著create site col
C++學習筆記(2)——程式的建立、編譯與除錯
單位新來的同事(也是非科班出生)問我程式設計用什麼軟體時,我大多會告訴他們VS2010或者VS2008(原諒我們單位用的IDE還如此老舊)。他們便會找來VS2010或者VS2008的教程,一步步照著做起來。新建工程,寫了一個main函式,列印了“helloworld”,點選了
小程式之雲函式的建立與使用
小程式雲開發之雲函式 雲函式的作用 我所知道的是,雲函式可以做一些前端做不了,必須在伺服器端做的複雜的操作。 比如:資料庫的多條紀錄同時更新與資料庫的多條紀錄同時刪除,這是在前端無法實現的,然後就可以通過雲函式來實現。 建立雲函式 我們需要在微信開發者工具的檔案管理裡面建立一個目錄和一個nodejs