1. 程式人生 > >plsql 程式包的建立與應用

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_USERAUTHIDDEFINER選項說明應用程式在呼叫函式時所使用的許可權模式,它們與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,DBAOBJECTS  

如,我們可以用: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應用程式,TCHARCHAR的相互轉換

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

實驗十五 GUI程式設計練習應用程式部署

                                            &

C++學習筆記(2)——程式建立、編譯除錯

單位新來的同事(也是非科班出生)問我程式設計用什麼軟體時,我大多會告訴他們VS2010或者VS2008(原諒我們單位用的IDE還如此老舊)。他們便會找來VS2010或者VS2008的教程,一步步照著做起來。新建工程,寫了一個main函式,列印了“helloworld”,點選了

程式之雲函式的建立使用

小程式雲開發之雲函式 雲函式的作用 我所知道的是,雲函式可以做一些前端做不了,必須在伺服器端做的複雜的操作。 比如:資料庫的多條紀錄同時更新與資料庫的多條紀錄同時刪除,這是在前端無法實現的,然後就可以通過雲函式來實現。 建立雲函式 我們需要在微信開發者工具的檔案管理裡面建立一個目錄和一個nodejs