PL/SQL包


在本章中,我們將討論PL/SQL中的包。 包是模式物件,將邏輯上相關的PL/SQL型別,變數和子程式分組。

一個包將有兩個強制性的部分 -

  • 包規範/格式
  • 包體或定義

包規範

規範是包的介面。它只是宣告可以從包外部參照的型別,變數,常數,異常,游標和子程式。 換句話說,它包含有關包的內容的所有資訊,但不包括子程式的程式碼。

所有放置在規範中的物件被稱為公共物件。任何不在包規範中但在包體中編碼的子程式稱為私有物件。

以下程式碼片段顯示了包含單個過程的包規範。可以在一個包中定義許多全域性變數和多個過程或函式。

SET SERVEROUTPUT ON SIZE 99999;
CREATE PACKAGE cust_sal AS 
   PROCEDURE find_sal(c_id customers.id%type); 
END cust_sal; 
/

當上面的程式碼在SQL提示符下執行時,它會產生以下結果 -

包體

包體具有包規範中宣告的各種方法程式碼和其他私有宣告,這些宣告對包之外的程式碼是隱藏的。

CREATE PACKAGE BODY語句用於建立包體。以下程式碼片段顯示了上面建立cust_sal包的包體宣告。假定已經在資料庫中建立了CUSTOMERS表,有關customers表的結構和資料,可參考以下SQL語句 -

CREATE TABLE CUSTOMERS( 
   ID   INT NOT NULL, 
   NAME VARCHAR (20) NOT NULL, 
   AGE INT NOT NULL, 
   ADDRESS CHAR (25), 
   SALARY   DECIMAL (18, 2),        
   PRIMARY KEY (ID) 
);  

-- 資料
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );  

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 );  

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (3, 'kaushik', 23, 'Kota', 2000.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 ); 

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 );  

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (6, 'Komal', 22, 'MP', 4500.00 );

基於上述customers表,建立一個簡單的包體 -

SET SERVEROUTPUT ON SIZE 99999;
CREATE OR REPLACE PACKAGE BODY cust_sal AS  

   PROCEDURE find_sal(c_id customers.id%TYPE) IS 
   c_sal customers.salary%TYPE; 
   BEGIN 
      SELECT salary INTO c_sal 
      FROM customers 
      WHERE id = c_id; 
      dbms_output.put_line('Salary: '|| c_sal); 
   END find_sal; 
END cust_sal; 
/

當上面的程式碼在SQL提示符下執行時,它會產生以下結果 -

使用包元素

包元素(變數,過程或函式)是用下面的語法來存取的 -

package_name.element_name;

考慮一下,假設已經在資料庫模式中建立了上面的包,下面的程式中需要呼叫cust_sal包趾的find_sal方法 -

SET SERVEROUTPUT ON SIZE 9999;
DECLARE 
   code customers.id%type := &cc_id; 
BEGIN 
   cust_sal.find_sal(code); 
END; 
/

當上述程式碼在SQL提示符下執行時,它會提示輸入客戶ID,當輸入一個ID時,顯示相應的工資如下 -

範例

以下程式提供了一個更完整的包體。使用儲存在資料庫中的CUSTOMERS表和以下記錄 -

Select * from customers;  

+----+----------+-----+-----------+----------+ 
| ID | NAME     | AGE | ADDRESS   | SALARY   | 
+----+----------+-----+-----------+----------+ 
|  1 | Ramesh   |  32 | Ahmedabad |  3000.00 | 
|  2 | Khilan   |  25 | Delhi     |  3000.00 | 
|  3 | kaushik  |  23 | Kota      |  3000.00 | 
|  4 | Chaitali |  25 | Mumbai    |  7500.00 | 
|  5 | Hardik   |  27 | Bhopal    |  9500.00 | 
|  6 | Komal    |  22 | MP        |  5500.00 | 
+----+----------+-----+-----------+----------+

包規範

SET SERVEROUTPUT ON SIZE 99999;
CREATE OR REPLACE PACKAGE c_package AS 
   -- Adds a customer 
   PROCEDURE addCustomer(c_id customers.id%TYPE, 
   c_name  customers.name%TYPE, 
   c_age  customers.age%TYPE, 
   c_addr customers.address%TYPE,  
   c_sal  customers.salary%TYPE); 

   -- Removes a customer 
   PROCEDURE delCustomer(c_id  customers.id%TYPE); 
   --Lists all customers 
   PROCEDURE listCustomer; 

END c_package; 
/

當上面的程式碼在SQL提示符下執行時,它會建立上面的包並顯示以下結果 -

建立程式包體

CREATE OR REPLACE PACKAGE BODY c_package AS 
   PROCEDURE addCustomer(c_id  customers.id%type, 
      c_name customers.name%type, 
      c_age  customers.age%type, 
      c_addr  customers.address%type,  
      c_sal   customers.salary%type) 
   IS 
   BEGIN 
      INSERT INTO customers (id,name,age,address,salary) 
         VALUES(c_id, c_name, c_age, c_addr, c_sal); 
   END addCustomer; 

   PROCEDURE delCustomer(c_id   customers.id%type) IS 
   BEGIN 
      DELETE FROM customers 
      WHERE id = c_id; 
   END delCustomer;  

   PROCEDURE listCustomer IS 
   CURSOR c_customers is 
      SELECT  name FROM customers; 
   TYPE c_list is TABLE OF customers.name%type; 
   name_list c_list := c_list(); 
   counter integer :=0; 
   BEGIN 
      FOR n IN c_customers LOOP 
      counter := counter +1; 
      name_list.extend; 
      name_list(counter) := n.name; 
      dbms_output.put_line('Customer(' ||counter|| ')'||name_list(counter)); 
      END LOOP; 
   END listCustomer;

END c_package; 
/

上面的例子使用了巢狀表,我們將在下一章討論巢狀表的概念。

當上面的程式碼在SQL提示符下執行時,它會產生以下結果 -

程式包體已建立。

使用程式包

以下程式使用程式包:c_package 中宣告和定義的方法。

SET SERVEROUTPUT ON SIZE 99999;
DECLARE 
   code customers.id%type:= 8; 
BEGIN 
   c_package.addcustomer(7, 'Andy Liu', 25, 'Chennai', 3500); 
   c_package.addcustomer(8, 'Kobe Bryant', 32, 'Delhi', 7500); 
   c_package.listcustomer; 
   c_package.delcustomer(code); 
   c_package.listcustomer; 
END; 
/

當上面的程式碼在SQL提示符下執行時,它會產生以下結果 -

Old salary:
New salary: 3500
Salary difference:
Old salary:
New salary: 7500
Salary difference:
Customer(1)Ramesh
Customer(2)Khilan
Customer(3)kaushik
Customer(4)Chaitali
Customer(5)Hardik
Customer(6)Komal
Customer(7)Andy Liu
Customer(8)Kobe Bryant
Customer(1)Ramesh
Customer(2)Khilan
Customer(3)kaushik
Customer(4)Chaitali
Customer(5)Hardik
Customer(6)Komal
Customer(7)Andy Liu

PL/SQL 過程已成功完成。