建立 employees_pkg 套件

此段落顯示如何建立 employees_pkg 套裝程式、其子程式的運作方式、如何將套裝程式的 EXECUTE 權限授予需要的使用者,以及這些使用者如何呼叫其中一個子程式。

若要建立 employees_pkg 套裝軟體:

  1. 以使用者 app_code 連線至資料庫。

    如需相關指示,請參閱從 SQL*Plus 連線至 Oracle AI Database從 SQL Developer 連線至 Oracle AI Database

  2. 建立這些同義字:

    CREATE OR REPLACE SYNONYM employees FOR app_data.employees;
    CREATE OR REPLACE SYNONYM departments FOR app_data.departments;
    CREATE OR REPLACE SYNONYM jobs FOR app_data.jobs;
    CREATE OR REPLACE SYNONYM job_history FOR app_data.job_history;

    您可以在 SQL*Plus 或 SQL Developer 的「工作表」中輸入 CREATE SYNONYM 敘述句。或者,您也可以使用 SQL Developer 工具「建立同義字」來建立同義字。

  3. 建立薪資配套規格。

  4. 建立套件主體。

另請參閱:

建立 employees_pkg 的套裝軟體規格

注意:您必須以 app_code 使用者身分連線至資料庫。

若要為 employees_pkg (經理的 API) 建立套裝程式規格,請使用下列 CREATE PACKAGE 敘述句。您可以在 SQL*Plus 或 SQL Developer 的「工作表」中輸入敘述句。或者,您也可以使用 SQL Developer 工具「建立套裝程式」建立套裝程式。

CREATE OR REPLACE PACKAGE employees_pkg
AS
  PROCEDURE get_employees_in_dept
    ( p_deptno     IN     employees.department_id%TYPE,
      p_result_set IN OUT SYS_REFCURSOR );

  PROCEDURE get_job_history
    ( p_employee_id  IN     employees.department_id%TYPE,
      p_result_set   IN OUT SYS_REFCURSOR );

  PROCEDURE show_employee
    ( p_employee_id  IN     employees.employee_id%TYPE,
      p_result_set   IN OUT SYS_REFCURSOR );

  PROCEDURE update_salary
    ( p_employee_id IN employees.employee_id%TYPE,
      p_new_salary  IN employees.salary%TYPE );

  PROCEDURE change_job
    ( p_employee_id IN employees.employee_id%TYPE,
      p_new_job     IN employees.job_id%TYPE,
      p_new_salary  IN employees.salary%TYPE := NULL,
      p_new_dept    IN employees.department_id%TYPE := NULL );

END employees_pkg;
/

另請參閱:

建立 employees_pkg 的套裝軟體主體

注意:您必須以 app_code 使用者身分連線至資料庫。

若要為經理人員 API employees_pkg 建立套裝程式主體,請使用下列 CREATE PACKAGE BODY 敘述句。您可以在 SQL*Plus 或 SQL Developer 的「工作表」中輸入敘述句。或者,您可以使用 SQL Developer 工具「建立主體」來建立套裝程式。

CREATE OR REPLACE PACKAGE BODY employees_pkg
AS
  PROCEDURE get_employees_in_dept
    ( p_deptno     IN     employees.department_id%TYPE,
      p_result_set IN OUT SYS_REFCURSOR )
  IS
     l_cursor SYS_REFCURSOR;
  BEGIN
    OPEN p_result_set FOR
      SELECT e.employee_id,
        e.first_name || ' ' || e.last_name name,
        TO_CHAR( e.hire_date, 'Dy Mon ddth, yyyy' ) hire_date,
        j.job_title,
        m.first_name || ' ' || m.last_name manager,
        d.department_name
      FROM employees e INNER JOIN jobs j ON (e.job_id = j.job_id)
        LEFT OUTER JOIN employees m ON (e.manager_id = m.employee_id)
        INNER JOIN departments d ON (e.department_id = d.department_id)
      WHERE e.department_id = p_deptno ;
  END get_employees_in_dept;

  PROCEDURE get_job_history
    ( p_employee_id  IN     employees.department_id%TYPE,
      p_result_set   IN OUT SYS_REFCURSOR )
  IS
  BEGIN
    OPEN p_result_set FOR
      SELECT e.First_name || ' ' || e.last_name name, j.job_title,
        e.job_start_date start_date,
        TO_DATE(NULL) end_date
      FROM employees e INNER JOIN jobs j ON (e.job_id = j.job_id)
      WHERE e.employee_id = p_employee_id
      UNION ALL
      SELECT e.First_name || ' ' || e.last_name name,
        j.job_title,
        jh.start_date,
        jh.end_date
      FROM employees e INNER JOIN job_history jh
        ON (e.employee_id = jh.employee_id)
        INNER JOIN jobs j ON (jh.job_id = j.job_id)
      WHERE e.employee_id = p_employee_id
      ORDER BY start_date DESC;
  END get_job_history;

  PROCEDURE show_employee
    ( p_employee_id  IN     employees.employee_id%TYPE,
      p_result_set   IN OUT sys_refcursor )
  IS
  BEGIN
    OPEN p_result_set FOR
      SELECT *
      FROM (SELECT TO_CHAR(e.employee_id) employee_id,
              e.first_name || ' ' || e.last_name name,
              e.email_addr,
              TO_CHAR(e.hire_date,'dd-mon-yyyy') hire_date,
              e.country_code,
              e.phone_number,
              j.job_title,
              TO_CHAR(e.job_start_date,'dd-mon-yyyy') job_start_date,
              to_char(e.salary) salary,
              m.first_name || ' ' || m.last_name manager,
              d.department_name
            FROM employees e INNER JOIN jobs j on (e.job_id = j.job_id)
              RIGHT OUTER JOIN employees m ON (m.employee_id = e.manager_id)
              INNER JOIN departments d ON (e.department_id = d.department_id)
            WHERE e.employee_id = p_employee_id)
      UNPIVOT (VALUE FOR ATTRIBUTE IN (employee_id, name, email_addr, hire_date,
        country_code, phone_number, job_title, job_start_date, salary, manager,
        department_name) );
  END show_employee;

  PROCEDURE update_salary
    ( p_employee_id IN employees.employee_id%type,
      p_new_salary  IN employees.salary%type )
  IS
  BEGIN
    UPDATE employees
    SET salary = p_new_salary
    WHERE employee_id = p_employee_id;
  END update_salary;

  PROCEDURE change_job
    ( p_employee_id IN employees.employee_id%TYPE,
      p_new_job     IN employees.job_id%TYPE,
      p_new_salary  IN employees.salary%TYPE := NULL,
      p_new_dept    IN employees.department_id%TYPE := NULL )
  IS
  BEGIN
    INSERT INTO job_history (employee_id, start_date, end_date, job_id,
      department_id)
    SELECT employee_id, job_start_date, TRUNC(SYSDATE), job_id, department_id
      FROM employees
      WHERE employee_id = p_employee_id;

    UPDATE employees
    SET job_id = p_new_job,
      department_id = NVL( p_new_dept, department_id ),
      salary = NVL( p_new_salary, salary ),
      job_start_date = TRUNC(SYSDATE)
    WHERE employee_id = p_employee_id;
  END change_job;
END employees_pkg;
/

另請參閱:

教學課程:顯示 employees_pkg 子程式的運作方式

本教學課程使用 SQL*Plus 顯示 employees_pkg 套裝程式的子程式如何運作。此教學課程也顯示觸發器 employees_aiufer 和 CHECK 限制 job_history_date_check 的運作方式。

注意:您必須以 SQL*Plus 使用者 app_code 的身分連線到 Oracle AI Database。

若要使用 SQL*Plus 來顯示 employees_pkg 子程式的運作方式:

  1. 使用格式化指令可以提高輸出的可讀性。舉例而言:

    SET LINESIZE 80
    SET RECSEP WRAPPED
    SET RECSEPCHAR "="
    COLUMN NAME FORMAT A15 WORD_WRAPPED
    COLUMN HIRE_DATE FORMAT A20 WORD_WRAPPED
    COLUMN DEPARTMENT_NAME FORMAT A10 WORD_WRAPPED
    COLUMN JOB_TITLE FORMAT A29 WORD_WRAPPED
    COLUMN MANAGER FORMAT A11 WORD_WRAPPED
  2. 宣告子程式參數 p_result_set 值的連結變數:

    VARIABLE c REFCURSOR
  3. 在部門 90 顯示員工:

    EXEC employees_pkg.get_employees_in_dept( 90, :c );
    PRINT c

    結果:

    EMPLOYEE_ID NAME            HIRE_DATE            JOB_TITLE
    
    ----------- --------------- -------------------- --------------------------
    MANAGER     DEPARTMENT
    
    ----------- ----------
            100 Steven King     Tue Jun 17th, 2003   President
                Executive                                                         ===========================================================================
            102 Lex De Haan     Sat Jan 13th, 2001   Administration Vice President
    Steven King Executive
    ===========================================================================
            101 Neena Kochhar   Wed Sep 21st, 2005   Administration Vice President
    Steven King Executive
    ===========================================================================
  4. 顯示員工 101 的職務記錄:

    EXEC employees_pkg.get_job_history( 101, :c );
    PRINT c

    結果:

    NAME            JOB_TITLE                     START_DAT END_DATE
    
    --------------- ----------------------------- --------- ---------
    Neena Kochhar   Administration Vice President 16-MAR-05
    Neena Kochhar   Accounting Manager            28-OCT-01 15-MAR-05
    Neena Kochhar   Public Accountant             21-SEP-97 27-OCT-01
  5. 顯示員工 101 的一般資訊:

    EXEC employees_pkg.show_employee( 101, :c );
    PRINT c

    結果:

    ATTRIBUTE       VALUE
    
    --------------- ----------------------------------------------
    EMPLOYEE_ID     101
    NAME            Neena Kochhar
    EMAIL_ADDR      NKOCHHAR
    HIRE_DATE       21-sep-2005
    COUNTRY_CODE    +1
    PHONE_NUMBER    515.123.4568
    
    JOB_TITLE       Administration Vice President
    JOB_START_DATE  16-mar-05
    
    SALARY          17000
    MANAGER         Steven King
    DEPARTMENT_NAME Executive
    
    11 rows selected.
  6. 顯示職務管理副總裁的相關資訊:

    SELECT * FROM jobs WHERE job_title = 'Administration Vice President';

    結果:

    JOB_ID     JOB_TITLE                     MIN_SALARY MAX_SALARY
    
    ---------- ----------------------------- ---------- ----------
    AD_VP      Administration Vice President      15000      30000
  7. 嘗試讓員工 101 在其職務範圍外的新薪資:

    EXEC employees_pkg.update_salary( 101, 30001 );

    結果:

    SQL> EXEC employees_pkg.update_salary( 101, 30001 );
    BEGIN employees_pkg.update_salary( 101, 30001 ); END;
    
    *
    ERROR at line 1:
    ORA-20002: Salary modification invalid
    ORA-06512: at "APP_DATA.EMPLOYEES_AIUFER", line 13
    
    ORA-04088: error during execution of trigger 'APP_DATA.EMPLOYEES_AIUFER'
    ORA-06512: at "APP_CODE.EMPLOYEES_PKG", line 77
    ORA-06512: at line 1
  8. 給予員工 101 在其職務範圍內的新薪資,並再次顯示其的一般資訊:

    EXEC employees_pkg.update_salary( 101, 18000 );
    EXEC employees_pkg.show_employee( 101, :c );
    PRINT c

    結果:

    ATTRIBUTE       VALUE
    
    --------------- ----------------------------------------------
    EMPLOYEE_ID     101
    NAME            Neena Kochhar
    EMAIL_ADDR      NKOCHHAR
    HIRE_DATE       21-sep-2005
    COUNTRY_CODE    +1
    PHONE_NUMBER    515.123.4568
    JOB_TITLE       Administration Vice President
    JOB_START_DATE  16-mar-05
    
    SALARY          18000
    MANAGER         Steven King
    DEPARTMENT_NAME Executive
    
    11 rows selected.
  9. 將員工 101 的職務變更為其目前職務,薪資較低:

    EXEC employees_pkg.change_job( 101, 'AD_VP', 17500, 90 );

    結果:

    SQL> exec employees_pkg.change_job( 101, 'AD_VP', 17500, 90 );
    BEGIN employees_pkg.change_job( 101, 'AD_VP', 17500, 80 ); END;
    
    *
    ERROR at line 1:
    
    ORA-02290: check constraint (APP_DATA.JOB_HISTORY_DATE_CHECK) violated
    ORA-06512: at "APP_CODE.EMPLOYEES_PKG", line 101
    ORA-06512: at line 1
  10. 顯示員工的相關資訊。(請注意,先前步驟中的陳述式並未變更薪資;其為 18000,而非 17500。)

    exec employees_pkg.show_employee( 101, :c );
    print c

    結果:

    ATTRIBUTE       VALUE
    
    --------------- ----------------------------------------------
    EMPLOYEE_ID     101
    NAME            Neena Kochhar
    EMAIL_ADDR      NKOCHHAR
    HIRE_DATE       21-sep-2005
    COUNTRY_CODE    +1
    PHONE_NUMBER    515.123.4568
    JOB_TITLE       Administration Vice President
    JOB_START_DATE  10-mar-2015
    SALARY          18000
    MANAGER         Steven King
    DEPARTMENT_NAME Executive
    
    11 rows selected.

另請參閱:

將 EXECUTE 權限授予 app_user 和 app_admin_user

注意:您必須以 app_code 使用者身分連線至資料庫。

若要將套裝軟體 employees_pkg 的 EXECUTE 權限授予 app_user (通常是管理員) 和 app_admin_user (應用程式管理員),請使用下列 GRANT 敘述句 (無論順序)。您可以在 SQL*Plus 或 SQL Developer 的「工作表」中輸入敘述句。

GRANT EXECUTE ON employees_pkg TO app_user;
GRANT EXECUTE ON employees_pkg TO app_admin_user;

另請參閱:

教學課程:以 app_user 或 app_admin_user 的身分呼叫 get_job_history

本教學課程使用 SQL*Plus,說明如何以使用者 app_user (通常是管理員) 或 app_admin_user (應用程式管理員) 的身分呼叫子程式 app_code.employees_pkg.get_job_history。

以 app_user 或 app_admin_user 身分呼叫 employees_pkg.get_job_history:

  1. 從 SQL*Plus,以使用者 app_user 或 app_admin_user 的身分連線至資料庫。

    如需指示,請參閱 Connecting to Oracle AI Database from SQL*Plus

  2. 建立下列同義字:

    CREATE SYNONYM employees_pkg FOR app_code.employees_pkg;
  3. 顯示員工 101 的職務記錄:

    EXEC employees_pkg.get_job_history( 101, :c );
    PRINT c

    結果:

    NAME            JOB_TITLE                     START_DAT END_DATE
    
    --------------- ----------------------------- --------- ---------
    Neena Kochhar   Administration Vice President 16-MAR-05 15-MAY-12
    Neena Kochhar   Accounting Manager            28-OCT-01 15-MAR-05
    Neena Kochhar   Public Accountant             21-SEP-97 27-OCT-01