Oracle PL/SQL Tutorial/Function Procedure Packages/Packages — различия между версиями

Материал из SQL эксперт
Перейти к: навигация, поиск
м (1 версия)
 
(нет различий)

Текущая версия на 10:11, 26 мая 2010

All packages can be recompiled by using the Oracle utility dbms_utility:

execute dbms_utility.rupile_all


A Package Specification and its body

SQL>
SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
  2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
  3    First_Name         VARCHAR2(10 BYTE),
  4    Last_Name          VARCHAR2(10 BYTE),
  5    Start_Date         DATE,
  6    End_Date           DATE,
  7    Salary             Number(8,2),
  8    City               VARCHAR2(10 BYTE),
  9    Description        VARCHAR2(15 BYTE)
 10  )
 11  /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2               values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
  3  /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
  2  /
ID   FIRST_NAME           LAST_NAME            START_DAT END_DATE      SALARY CITY       DESCRIPTION
---- -------------------- -------------------- --------- --------- ---------- ---------- ---------------
01   Jason                Martin               25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
02   Alison               Mathews              21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
03   James                Smith                12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
04   Celia                Rice                 24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
05   Robert               Black                15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
06   Linda                Green                30-JUL-87 04-JAN-96    4322.78 New York   Tester
07   David                Larry                31-DEC-90 12-FEB-98    7897.78 New York   Manager
08   James                Cat                  17-SEP-96 15-APR-02    1232.78 Vancouver  Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE EmployeePackage AS
  2    PROCEDURE AddEmployee(p_EmployeeID    IN Employee.id%TYPE,
  3                          p_first_name    IN Employee.first_name%TYPE,
  4                          p_last_name     IN Employee.last_name%TYPE);
  5
  6    -- Removes the specified student from the specified class.
  7    PROCEDURE RemoveEmployee(p_EmployeeID  IN Employee.id%TYPE,
  8                             p_first_name    IN Employee.first_name%TYPE,
  9                             p_last_name     IN Employee.last_name%TYPE);
 10
 11    -- Exception raised by RemoveEmployee.
 12    e_EmployeeNotRegistered EXCEPTION;
 13
 14    -- Table type used to hold student info.
 15    TYPE t_EmployeeIDTable IS TABLE OF Employee.id%TYPE INDEX BY BINARY_INTEGER;
 16
 17    -- Returns a PL/SQL table containing the Employee currently
 18    -- in the specified class.
 19    PROCEDURE EmployeeList(p_first_name  IN  Employee.first_name%TYPE,
 20                           p_last_name   IN  Employee.last_name%TYPE,
 21                           p_IDs         OUT t_EmployeeIDTable,
 22                           p_NumEmployees IN OUT BINARY_INTEGER);
 23  END EmployeePackage;
 24  /
SP2-0808: Package created with compilation warnings
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY EmployeePackage AS
  2    PROCEDURE AddEmployee(p_EmployeeID    IN Employee.id%TYPE,
  3                          p_first_name    IN Employee.first_name%TYPE,
  4                          p_last_name     IN Employee.last_name%TYPE) IS
  5    BEGIN
  6      INSERT INTO Employee (id, first_name, last_name) VALUES (p_EmployeeID, p_first_name, p_last_name);
  7      COMMIT;
  8    END AddEmployee;
  9
 10    PROCEDURE RemoveEmployee(p_EmployeeID    IN Employee.id%TYPE,
 11                             p_first_name    IN Employee.first_name%TYPE,
 12                             p_last_name     IN Employee.last_name%TYPE) IS
 13    BEGIN
 14      DELETE FROM Employee
 15        WHERE id = p_EmployeeID
 16        AND first_name = p_first_name
 17        AND last_name = p_last_name;
 18
 19      -- Check to see if the DELETE operation was successful. If
 20      -- it didn"t match any rows, raise an error.
 21      IF SQL%NOTFOUND THEN
 22        RAISE e_EmployeeNotRegistered;
 23      END IF;
 24
 25      COMMIT;
 26    END RemoveEmployee;
 27
 28
 29    -- Returns a PL/SQL table containing the Employee currently
 30    -- in the specified class.
 31    PROCEDURE EmployeeList(p_first_name  IN  Employee.first_name%TYPE,
 32                           p_last_name   IN  Employee.last_name%TYPE,
 33                           p_IDs         OUT t_EmployeeIDTable,
 34                           p_NumEmployees IN OUT BINARY_INTEGER) IS
 35
 36      v_EmployeeID  Employee.id%TYPE;
 37
 38      -- Local cursor to fetch the registered Employee.
 39      CURSOR c_RegisteredEmployees IS
 40        SELECT id
 41          FROM Employee
 42          WHERE first_name = p_first_name
 43          AND last_name = p_last_name;
 44    BEGIN
 45      /* p_NumEmployees will be the table index. It will start at
 46         0, and be incremented each time through the fetch loop.
 47         At the end of the loop, it will have the number of rows
 48         fetched, and therefore the number of rows returned in
 49         p_IDs. */
 50      p_NumEmployees := 0;
 51
 52      OPEN c_RegisteredEmployees;
 53      LOOP
 54        FETCH c_RegisteredEmployees INTO v_EmployeeID;
 55        EXIT WHEN c_RegisteredEmployees%NOTFOUND;
 56
 57        p_NumEmployees := p_NumEmployees + 1;
 58        p_IDs(p_NumEmployees) := v_EmployeeID;
 59      END LOOP;
 60    END EmployeeList;
 61  END EmployeePackage;
 62  /
SP2-0810: Package Body created with compilation warnings
SQL>
SQL> --Calling a Packaged Procedure
SQL> DECLARE
  2    v_HistoryEmployees EmployeePackage.t_EmployeeIDTable;
  3    v_NumEmployees     BINARY_INTEGER := 20;
  4  BEGIN
  5    EmployeePackage.EmployeeList("James", "Cat", v_HistoryEmployees,v_NumEmployees);
  6
  7    -- Insert these Employee into temp_table.
  8    FOR v_LoopCounter IN 1..v_NumEmployees LOOP
  9      DBMS_OUTPUT.put_line(v_HistoryEmployees(v_LoopCounter));
 10    END LOOP;
 11  END;
 12  /
08
PL/SQL procedure successfully completed.
SQL>
SQL>
SQL>
SQL>
SQL> -- clean the table
SQL> drop table Employee
  2  /
Table dropped.
SQL>


A Subtypes Example

SQL>
SQL> create or replace package pkg_subtype is
  2    subtype fullName is VARCHAR2(61);
  3  end pkg_subtype;
  4  /
Package created.
SQL> declare
  2    v_fullName_sty pkg_subtype.fullName;
  3  begin
  4    v_fullName_sty := "M C";
  5  end;
  6  /
PL/SQL procedure successfully completed.
SQL>
SQL>


Calling a Cursor Declared in a Different Package

-- create demo table
create table Employee(
  ID                 VARCHAR2(4 BYTE)         NOT NULL,
  First_Name         VARCHAR2(10 BYTE),
  Last_Name          VARCHAR2(10 BYTE),
  Start_Date         DATE,
  End_Date           DATE,
  Salary             Number(8,2),
  City               VARCHAR2(10 BYTE),
  Description        VARCHAR2(15 BYTE)
)
/
-- prepare data
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
             values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
              values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
              values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
              values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
              values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
              values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
              values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
/
insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
              values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
/
-- display data in the table
select * from Employee
/
--Here is the package spec where the cursor is declared.
create or replace package pkg_Util is
    cursor c_emp is select * from employee;
    r_emp c_emp%ROWTYPE;
end;
/
ge created.
--Here is a different package that references the cursor
create or replace package body pkg_aDifferentUtil is
    procedure p_printEmps is
    begin
        open pkg_Util.c_emp;
        loop
            fetch pkg_Util.c_emp into pkg_Util.r_emp;
            exit when pkg_Util.c_emp%NOTFOUND;
            DBMS_OUTPUT.put_line(pkg_Util.r_emp.first_Name);
        end loop;
        close pkg_Util.c_emp;
     end;
end;
/
 -- clean the table
drop table Employee
/SQL>


Calling Functions and Procedures in a Package

When calling functions and procedures in a package, you include the package name in the call.



SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
  2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
  3    First_Name         VARCHAR2(10 BYTE),
  4    Last_Name          VARCHAR2(10 BYTE),
  5    Start_Date         DATE,
  6    End_Date           DATE,
  7    Salary             Number(8,2),
  8    City               VARCHAR2(10 BYTE),
  9    Description        VARCHAR2(15 BYTE)
 10  )
 11  /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2               values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
  3  /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
  2  /
ID   FIRST_NAME LAST_NAME  START_DAT END_DATE      SALARY CITY       DESCRIPTION
---- ---------- ---------- --------- --------- ---------- ---------- ---------------
01   Jason      Martin     25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
02   Alison     Mathews    21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
03   James      Smith      12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
04   Celia      Rice       24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
05   Robert     Black      15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
06   Linda      Green      30-JUL-87 04-JAN-96    4322.78 New York   Tester
07   David      Larry      31-DEC-90 12-FEB-98    7897.78 New York   Manager
08   James      Cat        17-SEP-96 15-APR-02    1232.78 Vancouver  Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE employee_package AS
  2    TYPE t_ref_cursor IS REF CURSOR;
  3    FUNCTION get_employee_ref_cursor RETURN t_ref_cursor;
  4    PROCEDURE update_salary (p_id IN VARCHAR2,p_factor IN NUMBER);
  5  END employee_package;
  6  /
Package created.
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY employee_package AS
  2    FUNCTION get_employee_ref_cursor
  3    RETURN t_ref_cursor IS
  4      employee_ref_cursor t_ref_cursor;
  5    BEGIN
  6      -- get the REF CURSOR
  7      OPEN employee_ref_cursor FOR
  8        SELECT id, first_name, salary
  9        FROM employee;
 10      -- return the REF CURSOR
 11      RETURN employee_ref_cursor;
 12    END get_employee_ref_cursor;
 13
 14    PROCEDURE update_salary (p_id IN VARCHAR2, p_factor IN NUMBER) AS
 15      v_employee_count INTEGER;
 16    BEGIN
 17        UPDATE employee
 18        SET salary = salary * p_factor;
 19        COMMIT;
 20    EXCEPTION
 21      WHEN OTHERS THEN
 22        -- perform a rollback when an exception occurs
 23        ROLLBACK;
 24    END update_salary;
 25  END employee_package;
 26  /
Package body created.
SQL>
SQL> SELECT employee_package.get_employee_ref_cursor
  2  FROM dual;
GET_EMPLOYEE_REF_CUR
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ID   FIRST_NAME     SALARY
---- ---------- ----------
01   Jason         1234.56
02   Alison        6661.78
03   James         6544.78
04   Celia         2344.78
05   Robert        2334.78
06   Linda         4322.78
07   David         7897.78
08   James         1232.78
8 rows selected.

SQL>
SQL>
SQL> -- clean the table
SQL> drop table Employee
  2  /
Table dropped.
SQL>


Calls procedure in a package

SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
  2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
  3    First_Name         VARCHAR2(10 BYTE),
  4    Last_Name          VARCHAR2(10 BYTE),
  5    Start_Date         DATE,
  6    End_Date           DATE,
  7    Salary             Number(8,2),
  8    City               VARCHAR2(10 BYTE),
  9    Description        VARCHAR2(15 BYTE)
 10  )
 11  /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2               values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
  3  /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
  2  /
ID   FIRST_NAME LAST_NAME  START_DAT END_DATE      SALARY CITY       DESCRIPTION
---- ---------- ---------- --------- --------- ---------- ---------- ---------------
01   Jason      Martin     25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
02   Alison     Mathews    21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
03   James      Smith      12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
04   Celia      Rice       24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
05   Robert     Black      15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
06   Linda      Green      30-JUL-87 04-JAN-96    4322.78 New York   Tester
07   David      Larry      31-DEC-90 12-FEB-98    7897.78 New York   Manager
08   James      Cat        17-SEP-96 15-APR-02    1232.78 Vancouver  Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE employee_package AS
  2    TYPE t_ref_cursor IS REF CURSOR;
  3    FUNCTION get_employee_ref_cursor RETURN t_ref_cursor;
  4    PROCEDURE update_salary (p_id IN VARCHAR2,p_factor IN NUMBER
  5    );
  6  END employee_package;
  7  /
Package created.
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY employee_package AS
  2    FUNCTION get_employee_ref_cursor
  3    RETURN t_ref_cursor IS
  4      employee_ref_cursor t_ref_cursor;
  5    BEGIN
  6      -- get the REF CURSOR
  7      OPEN employee_ref_cursor FOR
  8        SELECT id, first_name, salary
  9        FROM employee;
 10      -- return the REF CURSOR
 11      RETURN employee_ref_cursor;
 12    END get_employee_ref_cursor;
 13
 14    PROCEDURE update_salary (p_id IN VARCHAR2,p_factor IN NUMBER
 15    ) AS
 16      v_employee_count INTEGER;
 17    BEGIN
 18      -- count the number of employees with the
 19      -- supplied id (should be 1 if the employee exists)
 20      SELECT COUNT(*)
 21      INTO v_employee_count
 22      FROM employee
 23      WHERE id = p_id;
 24      -- if the employee exists (v_employee_count = 1) then
 25      -- update that employee"s pass1
 26      IF v_employee_count = 1 THEN
 27        UPDATE employee
 28        SET salary = salary * p_factor
 29        WHERE id = p_id;
 30        COMMIT;
 31      END IF;
 32    EXCEPTION
 33      WHEN OTHERS THEN
 34        -- perform a rollback when an exception occurs
 35        ROLLBACK;
 36    END update_salary;
 37  END employee_package;
 38  /
Package body created.
SQL>
SQL>
SQL> CALL employee_package.update_salary(3, 1.25);
Call completed.
SQL> -- clean the table
SQL> drop table Employee
  2  /
Table dropped.
SQL>
SQL>


Controlling access to packages

You can do this in one of two ways: a simple command or a wrapper package.

To grant a user rights to access a particular package:



grant execute on package_name to user


Creating a Package Body

You create a package body using the CREATE PACKAGE BODY statement.

The simplified syntax for the CREATE PACKAGE BODY statement is as follows:



SQL>
SQL> CREATE [OR REPLACE] PACKAGE BODY package_name
  2  {IS | AS}
  3    package_body
  4  END package_name;


where

package_name specifies the name of the package, which must match the package name previously set in the package specification.

package_body specifies the code for the procedures and functions, along with any variables and cursors.

Creating a Package Specification

You create a package specification using the CREATE PACKAGE statement.

The simplified syntax for the CREATE PACKAGE statement is as follows:



CREATE [OR REPLACE] PACKAGE package_name
{IS | AS}
  package_specification
END package_name;


Creating Packages and call its functions

After the specification is created, you create the body of the package.

The body of a package is a collection of schema objects that was declared in the specification.

If you perform any initialization in the package body, it is executed once when the package is initially referenced.

To reference the package"s subprograms and objects, you must use dot notation.

The Syntax for Dot Notation



package_name.type_name
package_name.object_name
package_name.subprogram_name


Crosss reference between two packages

SQL>
SQL> create or replace package myPackage
  2  as
  3    PROCEDURE P1;
  4    PROCEDURE P2;
  5    PROCEDURE P3;
  6    FUNCTION F1 return number;
  7    FUNCTION F2 return number;
  8  end;
  9  /
Package created.
SQL>
SQL> create or replace package myPackage2
  2  as
  3    PROCEDURE P3;
  4    PROCEDURE P4;
  5    PROCEDURE P5;
  6    FUNCTION F1 return number;
  7    FUNCTION F3 return number;
  8  end;
  9  /
Package created.
SQL>
SQL> create or replace package body myPackage2
  2  as
  3    PROCEDURE P3
  4    as
  5      begin
  6        myPackage.P3;
  7      end;
  8
  9    FUNCTION F1 return number
 10    as
 11      begin
 12        return myPackage.F1;
 13      end;
 14
 15    PROCEDURE P4
 16    as
 17      begin
 18        null;
 19      end;
 20
 21    PROCEDURE P5
 22    as
 23      begin
 24        null;
 25      end;
 26
 27    FUNCTION F3 return number
 28    as
 29      begin
 30        return 1;
 31      end;
 32  end;
 33  /
Package body created.
SQL>
SQL> create or replace package body myPackage
  2  as
  3    PROCEDURE P1
  4    as
  5      begin
  6        null;
  7      end;
  8
  9    PROCEDURE P2
 10    as
 11      begin
 12        null;
 13      end;
 14
 15    PROCEDURE P3
 16    as
 17      begin
 18        null;
 19      end;
 20
 21    FUNCTION F1 return number
 22    as
 23      begin
 24        return 1;
 25      end;
 26
 27    FUNCTION F2 return number
 28    as
 29      begin
 30        return 1;
 31      end;
 32  end;
 33  /
Package body created.
SQL>
SQL>


Dropping a Package

You drop a package using DROP PACKAGE.



SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
  2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
  3    First_Name         VARCHAR2(10 BYTE),
  4    Last_Name          VARCHAR2(10 BYTE),
  5    Start_Date         DATE,
  6    End_Date           DATE,
  7    Salary             Number(8,2),
  8    City               VARCHAR2(10 BYTE),
  9    Description        VARCHAR2(15 BYTE)
 10  )
 11  /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2               values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
  3  /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
  2  /
ID   FIRST_NAME LAST_NAME  START_DAT END_DATE      SALARY CITY       DESCRIPTION
---- ---------- ---------- --------- --------- ---------- ---------- ---------------
01   Jason      Martin     25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
02   Alison     Mathews    21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
03   James      Smith      12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
04   Celia      Rice       24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
05   Robert     Black      15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
06   Linda      Green      30-JUL-87 04-JAN-96    4322.78 New York   Tester
07   David      Larry      31-DEC-90 12-FEB-98    7897.78 New York   Manager
08   James      Cat        17-SEP-96 15-APR-02    1232.78 Vancouver  Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE employee_package AS
  2    TYPE t_ref_cursor IS REF CURSOR;
  3    FUNCTION get_employee_ref_cursor RETURN t_ref_cursor;
  4    PROCEDURE update_salary (p_id IN VARCHAR2,
  5      p_factor IN NUMBER
  6    );
  7  END employee_package;
  8  /
Package created.
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY employee_package AS
  2    FUNCTION get_employee_ref_cursor
  3    RETURN t_ref_cursor IS
  4      employee_ref_cursor t_ref_cursor;
  5    BEGIN
  6      -- get the REF CURSOR
  7      OPEN employee_ref_cursor FOR
  8        SELECT id, first_name, salary
  9        FROM employee;
 10      -- return the REF CURSOR
 11      RETURN employee_ref_cursor;
 12    END get_employee_ref_cursor;
 13
 14    PROCEDURE update_salary (p_id IN VARCHAR2,
 15      p_factor IN NUMBER
 16    ) AS
 17      v_employee_count INTEGER;
 18    BEGIN
 19      -- count the number of employees with the
 20      -- supplied id (should be 1 if the employee exists)
 21      SELECT COUNT(*)
 22      INTO v_employee_count
 23      FROM employee
 24      WHERE id = p_id;
 25      -- if the employee exists (v_employee_count = 1) then
 26      -- update that employee"s pass1
 27      IF v_employee_count = 1 THEN
 28        UPDATE employee
 29        SET salary = salary * p_factor
 30        WHERE id = p_id;
 31        COMMIT;
 32      END IF;
 33    EXCEPTION
 34      WHEN OTHERS THEN
 35        -- perform a rollback when an exception occurs
 36        ROLLBACK;
 37    END update_salary;
 38  END employee_package;
 39  /
Package body created.
SQL>
SQL>
SQL> SELECT object_name, procedure_name
  2  FROM user_procedures
  3  WHERE object_name = "EMPLOYEE_PACKAGE";
OBJECT_NAME                    PROCEDURE_NAME
------------------------------ ------------------------------
EMPLOYEE_PACKAGE               GET_EMPLOYEE_REF_CURSOR
EMPLOYEE_PACKAGE               UPDATE_SALARY
SQL>
SQL> DROP PACKAGE EMPLOYEE_PACKAGE;
SQL>
SQL> -- clean the table
SQL> drop table Employee
  2  /
Table dropped.
SQL>
SQL>
SQL>
SQL>


Dynamically create packages

SQL> declare
  2   x varchar2(32767);
  3  begin
  4   for i in 1 .. 300 loop
  5     x := x || " procedure X"||i||";";
  6   end loop;
  7   execute immediate "create or replace package aTest is "||x||" end;";
  8   x := replace(x,";"," is y number; begin y := 1; end;");
  9
 10   execute immediate "create or replace package body aTest is "||x||" end;";
 11  end;
 12  /
PL/SQL procedure successfully completed.
SQL>


Generate Random number

SQL> REM 05-RAND.SQL
SQL> REM This file contains the code for the Random package in
SQL> REM Chapter 5 of "Oracle PL/SQL Programming".  It illustrates
SQL> REM package initialization.
SQL>
SQL> REM This is version 1.0 of this file, updated 2/18/96.
SQL> REM Comments and questions should go to Scott Urman at
SQL> REM surman@us.oracle.ru.
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE Random AS
  2  /* Random number generator.  Uses the same algorithm as the
  3     rand() function in C. */
  4
  5    -- Used to change the seed.  From a given seed, the same
  6    -- sequence of random numbers will be generated.
  7    PROCEDURE ChangeSeed(p_NewSeed IN NUMBER);
  8
  9    -- Returns a random integer between 1 and 32767.
 10    FUNCTION Rand RETURN NUMBER;
 11    --PRAGMA RESTRICT_REFERENCES(rand, WNDS );
 12
 13    -- Same as Rand, but with a procedural interface.
 14    PROCEDURE GetRand(p_RandomNumber OUT NUMBER);
 15
 16    -- Returns a random integer between 1 and p_MaxVal.
 17    FUNCTION RandMax(p_MaxVal IN NUMBER) RETURN NUMBER;
 18   -- PRAGMA RESTRICT_REFERENCES(RandMax, WNDS);
 19
 20    -- Same as RandMax, but with a procedural interface.
 21    PROCEDURE GetRandMax(p_RandomNumber OUT NUMBER,
 22                         p_MaxVal IN NUMBER);
 23  END Random;
 24  /
Package created.
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY Random AS
  2
  3    /* Used for calculating the next number. */
  4    v_Multiplier  CONSTANT NUMBER := 22695477;
  5    v_Increment   CONSTANT NUMBER := 1;
  6
  7    /* Seed used to generate random sequence. */
  8    v_Seed        number := 1;
  9
 10    PROCEDURE ChangeSeed(p_NewSeed IN NUMBER) IS
 11    BEGIN
 12      v_Seed := p_NewSeed;
 13    END ChangeSeed;
 14
 15    FUNCTION Rand RETURN NUMBER IS
 16    BEGIN
 17      v_Seed := MOD(v_Multiplier * v_Seed + v_Increment,
 18                    (2 ** 32));
 19      RETURN BITAND(v_Seed/(2 ** 16), 32767);
 20    END Rand;
 21
 22    PROCEDURE GetRand(p_RandomNumber OUT NUMBER) IS
 23    BEGIN
 24      -- Simply call Rand and return the value.
 25      p_RandomNumber := Rand;
 26    END GetRand;
 27
 28    FUNCTION RandMax(p_MaxVal IN NUMBER) RETURN NUMBER IS
 29    BEGIN
 30      RETURN MOD(Rand, p_MaxVal) + 1;
 31    END RandMax;
 32
 33    PROCEDURE GetRandMax(p_RandomNumber OUT NUMBER,
 34                         p_MaxVal IN NUMBER) IS
 35    BEGIN
 36      -- Simply call RandMax and return the value.
 37      p_RandomNumber := RandMax(p_MaxVal);
 38    END GetRandMax;
 39
 40  BEGIN
 41    /* Package initialization.  Initialize the seed to the current
 42       time in seconds. */
 43    ChangeSeed(TO_NUMBER(TO_CHAR(SYSDATE, "SSSSS")));
 44  END Random;
 45  /
Package body created.
SQL>


Globals Stored in a Package

SQL>
SQL>
SQL> create or replace package pkg_global is
  2     function f_countryUSA_cd return VARCHAR2;
  3  end;
  4  /
Package created.
SQL> create or replace package body pkg_global is
  2     gv_countryUSA_cd VARCHAR2(3) := "USA";
  3
  4     function f_countryUSA_cd return VARCHAR2 is
  5     begin
  6        return gv_countryUSA_cd;
  7     end;
  8
  9  end;
 10  /
Package body created.
SQL>
SQL> select pkg_global.f_countryUSA_cd from dual;
F_COUNTRYUSA_CD
---------------------------------------------
USA
SQL>


Overloading Packaged Subprograms

SQL>
SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
  2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
  3    First_Name         VARCHAR2(10 BYTE),
  4    Last_Name          VARCHAR2(10 BYTE),
  5    Start_Date         DATE,
  6    End_Date           DATE,
  7    Salary             Number(8,2),
  8    City               VARCHAR2(10 BYTE),
  9    Description        VARCHAR2(15 BYTE)
 10  )
 11  /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2               values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
  3  /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
  2  /
ID   FIRST_NAME           LAST_NAME            START_DAT END_DATE      SALARY CITY       DESCRIPTION
---- -------------------- -------------------- --------- --------- ---------- ---------- ---------------
01   Jason                Martin               25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
02   Alison               Mathews              21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
03   James                Smith                12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
04   Celia                Rice                 24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
05   Robert               Black                15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
06   Linda                Green                30-JUL-87 04-JAN-96    4322.78 New York   Tester
07   David                Larry                31-DEC-90 12-FEB-98    7897.78 New York   Manager
08   James                Cat                  17-SEP-96 15-APR-02    1232.78 Vancouver  Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE EmployeePackage AS
  2    PROCEDURE AddEmployee(p_EmployeeID  IN Employee.id%TYPE,
  3                          p_first_name IN Employee.first_name%TYPE,
  4                          p_last_name     IN Employee.last_name%TYPE);
  5
  6    PROCEDURE AddEmployee(p_FirstName IN Employee.first_name%TYPE,
  7                         p_LastName  IN Employee.last_name%TYPE,
  8                         p_city IN Employee.city%TYPE);
  9
 10  END EmployeePackage;
 11  /
Package created.
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY EmployeePackage AS
  2
  3    PROCEDURE AddEmployee(p_EmployeeID  IN Employee.id%TYPE,
  4                          p_first_name IN Employee.first_name%TYPE,
  5                          p_last_name     IN Employee.last_name%TYPE) IS
  6    BEGIN
  7      INSERT INTO Employee (id, first_name, last_name)
  8        VALUES (p_EmployeeID, p_first_name, p_last_name);
  9      COMMIT;
 10    END AddEmployee;
 11
 12    -- Add a new student by name, rather than ID.
 13    PROCEDURE AddEmployee(p_FirstName IN Employee.first_name%TYPE,
 14                         p_LastName  IN Employee.last_name%TYPE,
 15                         p_city IN Employee.city%TYPE) IS
 16      v_EmployeeID Employee.ID%TYPE;
 17    BEGIN
 18      SELECT ID
 19        INTO v_EmployeeID
 20        FROM Employee
 21        WHERE first_name = p_FirstName
 22        AND last_name = p_LastName;
 23
 24      -- Now we can add the student by ID.
 25      INSERT INTO Employee (id, first_name, city)
 26        VALUES (v_EmployeeID, p_firstname, p_city);
 27      COMMIT;
 28    END AddEmployee;
 29
 30  END EmployeePackage;
 31  /
Package body created.
SQL>
SQL>
SQL>
SQL>
SQL> -- clean the table
SQL> drop table Employee
  2  /
Table dropped.
SQL>


package RECURSION

SQL> create package RECURSION is
  2   procedure A(p number);
  3   procedure B(p number);
  4   end;
  5  /

SQL> create or replace package body RECURSION is
  2
  3   procedure A(p number) is
  4   begin
  5        B(p+1);
  6   end;
  7
  8   procedure B(p number) is
  9   begin
 10       A(p+1);
 11   end;
 12
 13   end;
 14  /
Package body created.
SQL>
SQL>


Packages

  1. Packages encapsulate related functionality into one self-contained unit.
  2. Packages are typically made up of two components: a specification and a body.
  3. The package specification contains information about the package.
  4. The package specification lists the available procedures and functions.
  5. These are potentially available to all database users.
  6. The package specification generally doesn"t contain the code.
  7. The package body contains the actual code.

CREATE OR REPLACE PACKAGE command:



SQL> create or replace package pkg_test1
  2  as
  3      function getArea (i_rad NUMBER) return NUMBER;
  4      procedure p_print (i_str1 VARCHAR2 :="hello",
  5                         i_str2 VARCHAR2 :="world",
  6                         i_end VARCHAR2  :="!" );
  7  end;
  8  /
Package created.
SQL>
SQL> create or replace package body pkg_test1
  2  as
  3      function getArea (i_rad NUMBER)return NUMBER
  4      is
  5          v_pi NUMBER:=3.14;
  6      begin
  7         return v_pi * (i_rad ** 2);
  8      end;
  9
 10      procedure p_print(i_str1 VARCHAR2 :="hello",
 11                        i_str2 VARCHAR2 :="world",
 12                        i_end VARCHAR2  :="!" )
 13      is
 14      begin
 15          DBMS_OUTPUT.put_line(i_str1||","||i_str2||i_end);
 16      end;
 17  end;
 18  /
Package body created.


Package State

A package is always either valid or invalid.

A package is valid if none of its source code or objects it references have been dropped, replaced, or altered since the package specification was last recompiled.

a package is invalid if its source code or any object that it references has been dropped, altered, or replaced since the package specification was last recompiled.

When a package becomes invalid, Oracle will also make invalid any object that references the package.

27. 10. Packages 27. 10. 1. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Packages.htm">Packages</a> 27. 10. 2. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/PrivateVersusPublicPackageObjects.htm">Private Versus Public Package Objects</a> 27. 10. 3. Package State 27. 10. 4. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/RecompilingPackages.htm">Recompiling Packages</a> 27. 10. 5. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/AllpackagescanberecompiledbyusingtheOracleutilitydbmsutility.htm">All packages can be recompiled by using the Oracle utility dbms_utility:</a> 27. 10. 6. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CreatingaPackageSpecification.htm">Creating a Package Specification</a> 27. 10. 7. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CreatingaPackageBody.htm">Creating a Package Body</a> 27. 10. 8. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CreatingPackagesandcallitsfunctions.htm">Creating Packages and call its functions</a> 27. 10. 9. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CallingFunctionsandProceduresinaPackage.htm">Calling Functions and Procedures in a Package</a> 27. 10. 10. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/APackageSpecificationanditsbody.htm">A Package Specification and its body</a> 27. 10. 11. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/OverloadingPackagedSubprograms.htm">Overloading Packaged Subprograms</a> 27. 10. 12. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Callsprocedureinapackage.htm">Calls procedure in a package</a> 27. 10. 13. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/DroppingaPackage.htm">Dropping a Package</a> 27. 10. 14. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CallingaCursorDeclaredinaDifferentPackage.htm">Calling a Cursor Declared in a Different Package</a> 27. 10. 15. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Referencefieldsandmethodsinpackage.htm">Reference fields and methods in package</a> 27. 10. 16. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Controllingaccesstopackages.htm">Controlling access to packages</a> 27. 10. 17. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/GlobalsStoredinaPackage.htm">Globals Stored in a Package</a> 27. 10. 18. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/ASubtypesExample.htm">A Subtypes Example</a> 27. 10. 19. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/GenerateRandomnumber.htm">Generate Random number</a> 27. 10. 20. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Crosssreferencebetweentwopackages.htm">Crosss reference between two packages</a> 27. 10. 21. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/packageRECURSION.htm">package RECURSION</a> 27. 10. 22. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/UsingRESTRICTREFERENCESinaPackage.htm">Using RESTRICT_REFERENCES in a Package</a> 27. 10. 23. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/PLS00452SubprogramGETNAMEviolatesitsassociatedpragma.htm">PLS-00452: Subprogram "GETNAME" violates its associated pragma</a> 27. 10. 24. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Dynamicallycreatepackages.htm">Dynamically create packages</a>

PLS-00452: Subprogram "GETNAME" violates its associated pragma

SQL>
SQL>
SQL> create table product(
  2     product_id number(4)     not null,
  3     product_description varchar2(20) not null
  4  );
Table created.
SQL>
SQL> insert into product values (1,"Java");
1 row created.
SQL> insert into product values (2,"Oracle");
1 row created.
SQL> insert into product values (3,"C#");
1 row created.
SQL> insert into product values (4,"Javascript");
1 row created.
SQL> insert into product values (5,"Python");
1 row created.
SQL>
SQL>
SQL> create table company(
  2     product_id        number(4)    not null,
  3     company_id          NUMBER(8)    not null,
  4     company_short_name  varchar2(30) not null,
  5     company_long_name   varchar2(60)
  6  );
Table created.
SQL> insert into company values(1,1001,"A Inc.","Long Name A Inc.");
1 row created.
SQL> insert into company values(1,1002,"B Inc.","Long Name B Inc.");
1 row created.
SQL> insert into company values(1,1003,"C Inc.","Long Name C Inc.");
1 row created.
SQL> insert into company values(2,1004,"D Inc.","Long Name D Inc.");
1 row created.
SQL> insert into company values(2,1005,"E Inc.","Long Name E Inc.");
1 row created.
SQL> insert into company values(2,1006,"F Inc.","Long Name F Inc.");
1 row created.
SQL>
SQL> create table product_company(
  2     product_id           number(4) not null,
  3     product_description  varchar2(20) not null,
  4     company_id           NUMBER(8) not null,
  5     company_short_name   varchar2(30) not null,
  6     company_long_name    varchar2(60)
  7  );
Table created.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE myPackage
  2  IS
  3    FUNCTION getName(ip_product_id NUMBER,ip_company_id NUMBER)
  4    RETURN VARCHAR2;
  5    PRAGMA RESTRICT_REFERENCES(getName,WNDS,WNPS);
  6  END myPackage;
  7  /
Package created.
SQL>
SQL> show errors
No errors.
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY myPackage
  2  IS
  3    FUNCTION getName(ip_product_id NUMBER,ip_company_id NUMBER)
  4    RETURN VARCHAR2
  5    IS
  6      v_name VARCHAR2(120);
  7      v_product_description VARCHAR2(20);
  8      v_company_short_name VARCHAR2(30);
  9      v_company_long_name VARCHAR2(60);
 10    BEGIN
 11      SELECT "Org Name: (Short) "||company_short_name||" (Long) "||company_long_name
 12      INTO v_name
 13      FROM company
 14      WHERE product_id = ip_product_id
 15      AND company_id = ip_company_id;
 16      SELECT product_description
 17      INTO v_product_description
 18      FROM product
 19      WHERE product_id = ip_product_id;
 20      SELECT company_short_name,company_long_name
 21      INTO v_company_short_name,v_company_long_name
 22      FROM company
 23      WHERE product_id = ip_product_id
 24      AND company_id = ip_company_id;
 25      INSERT INTO product_company VALUES
 26      (ip_product_id,v_product_description,ip_company_id,
 27       v_company_short_name,v_company_long_name);
 28      RETURN (v_name);
 29    END getName;
 30  END myPackage;
 31  /
Warning: Package Body created with compilation errors.
SQL> show errors
Errors for PACKAGE BODY MYPACKAGE:
LINE/COL
--------
ERROR
-----------------------------------------------------------------
3/3
PLS-00452: Subprogram "GETNAME" violates its associated pragma
SQL>
SQL>
SQL> drop table company;
Table dropped.
SQL>
SQL> drop table product;
Table dropped.
SQL>
SQL> drop table product_company;
Table dropped.
SQL>


Private Versus Public Package Objects

For objects that are declared inside the package body, you are restricted to use within that package.

Therefore, PL/SQL code outside the package cannot reference any of the variables that were privately declared within the package.

Any items declared inside the package specification are visible outside the package.

These objects declared in the package specification are called public.

If the variable, constant, or cursor was declared in a package specification or body, their values persist for the duration of the user"s session.

The values are lost when the current user"s session terminates or the package is recompiled.

27. 10. Packages 27. 10. 1. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Packages.htm">Packages</a> 27. 10. 2. Private Versus Public Package Objects 27. 10. 3. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/PackageState.htm">Package State</a> 27. 10. 4. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/RecompilingPackages.htm">Recompiling Packages</a> 27. 10. 5. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/AllpackagescanberecompiledbyusingtheOracleutilitydbmsutility.htm">All packages can be recompiled by using the Oracle utility dbms_utility:</a> 27. 10. 6. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CreatingaPackageSpecification.htm">Creating a Package Specification</a> 27. 10. 7. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CreatingaPackageBody.htm">Creating a Package Body</a> 27. 10. 8. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CreatingPackagesandcallitsfunctions.htm">Creating Packages and call its functions</a> 27. 10. 9. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CallingFunctionsandProceduresinaPackage.htm">Calling Functions and Procedures in a Package</a> 27. 10. 10. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/APackageSpecificationanditsbody.htm">A Package Specification and its body</a> 27. 10. 11. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/OverloadingPackagedSubprograms.htm">Overloading Packaged Subprograms</a> 27. 10. 12. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Callsprocedureinapackage.htm">Calls procedure in a package</a> 27. 10. 13. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/DroppingaPackage.htm">Dropping a Package</a> 27. 10. 14. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/CallingaCursorDeclaredinaDifferentPackage.htm">Calling a Cursor Declared in a Different Package</a> 27. 10. 15. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Referencefieldsandmethodsinpackage.htm">Reference fields and methods in package</a> 27. 10. 16. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Controllingaccesstopackages.htm">Controlling access to packages</a> 27. 10. 17. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/GlobalsStoredinaPackage.htm">Globals Stored in a Package</a> 27. 10. 18. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/ASubtypesExample.htm">A Subtypes Example</a> 27. 10. 19. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/GenerateRandomnumber.htm">Generate Random number</a> 27. 10. 20. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Crosssreferencebetweentwopackages.htm">Crosss reference between two packages</a> 27. 10. 21. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/packageRECURSION.htm">package RECURSION</a> 27. 10. 22. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/UsingRESTRICTREFERENCESinaPackage.htm">Using RESTRICT_REFERENCES in a Package</a> 27. 10. 23. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/PLS00452SubprogramGETNAMEviolatesitsassociatedpragma.htm">PLS-00452: Subprogram "GETNAME" violates its associated pragma</a> 27. 10. 24. <A href="/Tutorial/Oracle/0540__Function-Procedure-Packages/Dynamicallycreatepackages.htm">Dynamically create packages</a>

Recompiling Packages

To recompile a package, use the ALTER PACKAGE command with the compile keyword.

Recompiling a package recompiles all objects defined within the package.

The following examples recompile just the body of a package.



ALTER PACKAGE inventory_pkg compile body


Reference fields and methods in package

SQL>
SQL>
SQL> create or replace package pkg_a is
  2        v_a number:=0;
  3        function a1 return NUMBER;
  4  end;
  5  /
Package created.
SQL> create or replace package body pkg_a is
  2      function a1 return NUMBER is
  3      begin
  4          return 0;
  5      end;
  6  end;
  7  /
Package body created.
SQL> create or replace package pkg_b is
  2      function b1 return NUMBER;
  3  end;
  4  /
Package created.
SQL> create or replace package body pkg_b is
  2      function b1 return NUMBER is
  3      begin
  4          return pkg_a.a1+1;
  5      end;
  6  end;
  7  /
Package body created.
SQL>
SQL>
SQL> select pkg_a.a1, pkg_b.b1 from dual;
        A1         B1
---------- ----------
         0          1
SQL>


Using RESTRICT_REFERENCES in a Package

SQL>
SQL>
SQL>
SQL> -- create demo table
SQL> create table Employee(
  2    ID                 VARCHAR2(4 BYTE)         NOT NULL,
  3    First_Name         VARCHAR2(10 BYTE),
  4    Last_Name          VARCHAR2(10 BYTE),
  5    Start_Date         DATE,
  6    End_Date           DATE,
  7    Salary             Number(8,2),
  8    City               VARCHAR2(10 BYTE),
  9    Description        VARCHAR2(15 BYTE)
 10  )
 11  /
Table created.
SQL>
SQL> -- prepare data
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2               values ("01","Jason",    "Martin",  to_date("19960725","YYYYMMDD"), to_date("20060725","YYYYMMDD"), 1234.56, "Toronto",  "Programmer")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("02","Alison",   "Mathews", to_date("19760321","YYYYMMDD"), to_date("19860221","YYYYMMDD"), 6661.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("03","James",    "Smith",   to_date("19781212","YYYYMMDD"), to_date("19900315","YYYYMMDD"), 6544.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("04","Celia",    "Rice",    to_date("19821024","YYYYMMDD"), to_date("19990421","YYYYMMDD"), 2344.78, "Vancouver","Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary,  City,       Description)
  2                values("05","Robert",   "Black",   to_date("19840115","YYYYMMDD"), to_date("19980808","YYYYMMDD"), 2334.78, "Vancouver","Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("06","Linda",    "Green",   to_date("19870730","YYYYMMDD"), to_date("19960104","YYYYMMDD"), 4322.78,"New York",  "Tester")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("07","David",    "Larry",   to_date("19901231","YYYYMMDD"), to_date("19980212","YYYYMMDD"), 7897.78,"New York",  "Manager")
  3  /
1 row created.
SQL> insert into Employee(ID,  First_Name, Last_Name, Start_Date,                     End_Date,                       Salary, City,        Description)
  2                values("08","James",    "Cat",     to_date("19960917","YYYYMMDD"), to_date("20020415","YYYYMMDD"), 1232.78,"Vancouver", "Tester")
  3  /
1 row created.
SQL>
SQL>
SQL>
SQL> -- display data in the table
SQL> select * from Employee
  2  /
ID   FIRST_NAME           LAST_NAME            START_DAT END_DATE      SALARY CITY       DESCRIPTION
---- -------------------- -------------------- --------- --------- ---------- ---------- ---------------
01   Jason                Martin               25-JUL-96 25-JUL-06    1234.56 Toronto    Programmer
02   Alison               Mathews              21-MAR-76 21-FEB-86    6661.78 Vancouver  Tester
03   James                Smith                12-DEC-78 15-MAR-90    6544.78 Vancouver  Tester
04   Celia                Rice                 24-OCT-82 21-APR-99    2344.78 Vancouver  Manager
05   Robert               Black                15-JAN-84 08-AUG-98    2334.78 Vancouver  Tester
06   Linda                Green                30-JUL-87 04-JAN-96    4322.78 New York   Tester
07   David                Larry                31-DEC-90 12-FEB-98    7897.78 New York   Manager
08   James                Cat                  17-SEP-96 15-APR-02    1232.78 Vancouver  Tester
8 rows selected.
SQL>
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE EmployeeOps AS
  2    FUNCTION FullName(p_ID IN employee.ID%TYPE)
  3      RETURN VARCHAR2;
  4    PRAGMA RESTRICT_REFERENCES(FullName, WNDS, WNPS, RNPS);
  5
  6    FUNCTION NumCity
  7      RETURN NUMBER;
  8    PRAGMA RESTRICT_REFERENCES(NumCity, WNDS, WNPS, RNPS);
  9  END EmployeeOps;
 10  /
Package created.
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY EmployeeOps AS
  2
  3    v_NumHist NUMBER;
  4
  5    FUNCTION FullName(p_ID IN employee.ID%TYPE)
  6      RETURN VARCHAR2 IS
  7      v_Result  VARCHAR2(100);
  8    BEGIN
  9      SELECT first_name || " " || last_name
 10        INTO v_Result
 11        FROM employee
 12        WHERE ID = p_ID;
 13
 14      RETURN v_Result;
 15    END FullName;
 16
 17    FUNCTION NumCity RETURN NUMBER IS
 18      v_Result NUMBER;
 19    BEGIN
 20      IF v_NumHist IS NULL THEN
 21        SELECT COUNT(*)
 22          INTO v_Result
 23          FROM employee
 24          WHERE city = "Vancouver";
 25        v_NumHist := v_Result;
 26      ELSE
 27        v_Result := v_NumHist;
 28      END IF;
 29
 30      RETURN v_Result;
 31    END NumCity;
 32  END EmployeeOps;
 33  /
Warning: Package Body created with compilation errors.
SQL>
SQL>
SQL>
SQL>
SQL> -- clean the table
SQL> drop table Employee
  2  /
Table dropped.
SQL>