1. 程式人生 > 實用技巧 >零基礎天池新聞推薦初學-04-排序模型+模型融合的簡單學習(TODO 待進一步完善)

零基礎天池新聞推薦初學-04-排序模型+模型融合的簡單學習(TODO 待進一步完善)

1. 程式包的概念

1.程式包定義

程式包用於將邏輯相關的PL/SQL塊或元素(變數、常量、過程、函式等)組織在一起,作為一個完整的單元儲存在資料庫中,用包名稱來標識程式包。程式包類似於面向物件中的類。

2.程式包的結構

3.包中可以包含的元素的性質

元素的性質

描述

在包中的位置

公共的(public)

在整個應用的全過程均有效

包的說明部分說明

私有的(private)

對包以外的過程和函式是不可見的

在包體部分說明和定義

區域性的

只在一個過程或函式內使用

在所屬過程或函式的內部說明和定義

2. 建立包頭

1.建立包頭的命令格式:

CREATE [OR REPLACE] PACKAGE <packagename> IS|AS
公共資料型別和物件宣告;
公共子程式和函式說明;
END [<資料包名稱>];

說明:

  1. 在包頭中宣告的元素(過程、函式、變數等)是公共元素,只在包體中宣告的元素是私有元素。
  2. 公共元素可以在包的外面單獨呼叫,但私有元素只能在包體內定義別的過程函式時被呼叫。
  3. 區域性變數是在包體內過程或函式中定義的變數,該區域性變數只能在該過程函式內使用,不能在包體內別的過程函式內使用。

2.建立包規範的語法:

CREATE [OR REPLACE] PACKAGE package_name{IS
| AS} type_definition| procedure_specification| function_specification| variable_declaration| exception_declaration| cursor_declaration| pragma_declaration END [ package_name];

例1 :建立一個包頭pkg_score,在包頭中(參考函式案例)
宣告一個函式,用於查詢某課程的課程型別;
宣告一個儲存過程,用於查詢某學生的成績資訊及課程型別,要求必修課輸出百分制成績,選修課或考查課輸出五分製成績。

CREATE OR REPLACE
PACKAGE pkg_score IS --宣告一個公有函式,用於查詢某課程的課程型別 FUNCTION course_type(cid char) RETURN nvarchar2 ; --宣告一個公有儲存過程,用於查詢某學生的成績資訊及課程型別,要求必修課輸出百分制成績,選修課或考查課輸出五分製成績。 PROCEDURE sele_stuscore(sid char); END pkg_score;

例2 :建立一個包頭prodcut_pkg,在包頭中
宣告一個記錄型別prod_row(包含產品編號、產品名稱、產品類別、單價、折扣資訊欄位);
宣告一個儲存過程sele_prod,用於查詢某產品編號的產品資訊;
宣告一個儲存過程update_prod,用於對摺扣資訊為1的產品價格打9.5折;
宣告一個函式max_price,用於計算某類產品的最高價格;
宣告一個儲存過程out_prod,用於輸出產品表中某類產品的產品編號、產品名稱、產品類別、單價、折扣資訊。

CREATE OR REPLACE PACKAGE product_pkg IS
 --宣告公有記錄型別存放產品資訊
TYPE prod_row IS RECORD
(prodid products.productid%type,
 prodname products.productname%type,
 cid products.categoryid%type,
 uprice products.unitprice%type,
 pdisc products.discontinued%type);
規範定義程式碼:
 --宣告公有儲存過程,查某產品編號的產品資訊
PROCEDURE sele_prod(pid IN products.productid%type,
            sele_prodrow OUT prod_row);
--宣告公有儲存過程更新打折產品單價
PROCEDURE update_prod;
 --宣告公有函式求某類產品的最高單價
FUNCTION max_price(cateid products.categoryid%type) RETURN number;
 --宣告公有儲存過程輸出某類產品的資訊
PROCEDURE out_prod(cateid products.categoryid%type);
END product_pkg;

3. 建立包體

建立包體的語法格式:

CREATE [OR REPLACE] PACKAGE BODY [Schema.]package_name
{IS|AS}
私有變數的定義|
私有型別的定義|
私有例外出錯處理的定義|
私有遊標的定義|
函式定義|
過程定義
[[BEGIN]
  [例項化程式碼]]   --只在使用者第一次呼叫程式包時執行一次
END [ package_name];
  • 1、聲明範圍對於資料包主體是區域性的
  • 2、除了在資料包主體內將不能訪問到宣告的型別和物件

例1(與建立包頭例1為同一道題) :建立一個包體pkg_score,在包體中包含:
用於查詢某課程的課程型別的公有函式;
用於根據學生成績返回’優、良、中、及、不及’五級分制的私有函式;
用於查詢某學生的成績資訊及課程型別的公有儲存過程,要求必修課輸出百分制成績,選修課或考查課輸出五分製成績。

CREATE OR REPLACE PACKAGE BODY pkg_score
IS
--用於查詢某課程的課程型別的公有函式;
FUNCTION course_type(cid char) RETURN nvarchar2  IS
   v_ctype nvarchar2(10);
   v_str char(1);
  BEGIN
      v_str:=substr(cid, 3, 1);  
     CASE v_str
         WHEN '1' THEN v_ctype:='必修課';
         WHEN '2' THEN v_ctype:='考查課';
          WHEN '3' THEN v_ctype:='選修課';
       ELSE
             v_ctype:='課程型別錯誤';
       END CASE;
    RETURN v_ctype;
END course_type;
--用於根據學生成績返回’優、良、中、及、不及’五級分制的私有函式;
FUNCTION five_score(s_score number)
RETURN varchar2
IS
     ss nvarchar2(10);
     BEGIN
      CASE
       WHEN s_score>=90 and s_score<=100 THEN ss:='優秀';
       WHEN s_score>=60 and s_score<90 THEN ss:='良好';
       WHEN s_score>=70 and s_score<60 THEN ss:='中等';
       WHEN s_score>=60 and s_score<70 THEN ss:='及格';
       ELSE    ss:='不及格';     
END CASE;
Return ss;
END five_score;
--用於查詢某學生的成績資訊及課程型別的公有儲存過程,要求必修課輸出百分制成績,選修課或考查課輸出五分製成績。
PROCEDURE sele_stuscore(sid char)   IS
    BEGIN
   FOR i IN (select * from stu_scores where stu_id=sid) LOOP
        IF course_type(i.course_id) ='必修課' THEN   
          dbms_output.put_line('學號:'|| i.stu_id || '  課程:'||i.course_id||'  課程型別:'||course_type(i.course_id)||'   成績:'||i.score);
        ELSE
               dbms_output.put_line('學號:'|| i.stu_id || '  課程:'||i.course_id||'  課程型別:'||course_type(i.course_id)||'   成績:'||five_score(i.score));
         END IF;
   END LOOP;
END sele_stuscore;
END pkg_score;

例2(與建立包頭例2為同一道題) :建立一個包體prodcut_pkg,在包體中實現以下功能:
建立一個儲存過程sele_prod,用於查詢某產品編號的產品資訊;
建立一個儲存過程update_prod,用於對摺扣資訊為1的產品價格打9.5折;
建立一個函式max_price,用於計算某類產品的最高價格;
建立一個儲存過程out_prod,用於輸出產品表中某類產品的產品編號、產品名稱、產品類別、單價資訊。

CREATE OR REPLACE PACKAGE BODY product_pkg AS
--查詢某產品編號的產品資訊
PROCEDURE sele_prod(pid IN products.productid%type, p_row OUT prod_row) IS
BEGIN
  SELECT productid, productname, categoryid, unitprice, discontinued INTO p_row
  FROM products WHERE productid=pid;
  EXCEPTION
     WHEN no_data_found THEN
          raise_application_error(-20000, '產品不存在');
END sele_prod;
--對摺扣資訊為1的產品價格打9.5折
PROCEDURE update_prod   IS
   no_update EXCEPTION;
BEGIN
  UPDATE products
  SET unitprice=unitprice*0.95
  WHERE discontinued='1';
  IF SQL%NOTFOUND THEN
      RAISE no_update;
  END IF;
  EXCEPTION
     WHEN no_update THEN
          raise_application_error(-20006, '沒有打折的產品');
END  update_prod;

--計算某類產品的最高價格
FUNCTION max_price(cateid products.categoryid%type) RETURN number IS
  mprice number;  --區域性變數
BEGIN
  SELECT avg(unitprice) INTO mprice
  FROM products WHERE categoryid=cateid
  Group by categoryid;
  RETURN mprice;
  EXCEPTION
     WHEN no_data_found THEN
          raise_application_error(-20002, '該類產品不存在');
         RETURN 0;
END max_price;
--輸出產品表中某類產品的產品編號、產品名稱、產品類別、單價資訊
PROCEDURE out_prod(cateid products.categoryid%type)
IS
  BEGIN
FOR p_row  IN (SELECT *  FROM products WHERE categoryid=cateid) LOOP
   dbms_output.put_line('產品編號:'||p_row.productid);
   dbms_output.put_line('產品名稱:'||p_row.productname);
   dbms_output.put_line(' 類別編號:'||p_row.categoryid);
   dbms_output.put_line(' 單價:'||p_row.unitprice);
END LOOP;
END out_prod;
END  product_pkg;

4.包中函式與過程的執行

1.呼叫包中過程的語法格式:

包名. 過程名[(引數……)]
例:在SQL*PLUS中執行pkg_score包中的儲存過程sele

SQL> EXEC pkg_score.sele_stuscore(1)

2.呼叫包中函式的語法格式為:

declare  變數名  資料型別(長度)
         begin
         變數名:=包名.函式名(引數);
       dbms_output.put_line(變數名);
      end;

3.程式包的刪除

語法:drop package 包名;

5.包的優點

1、規範化應用程式的開發

2、方便對儲存過程和函式的組織

  • 將相關的過程和函式組織在一起
  • 在一個使用者的環境中解決命名衝突

3、方便對儲存過程和函式的安全性管理

  • 整個包的訪問許可權只需要一次性授權
  • 區分公共過程和私有過程。公共過程在包外可以被呼叫,私有過程在包外不能被呼叫。

4、為使用者會話提供狀態確認資訊

  • 在各種環境和過程中均可引用識別符號(即包內的公共變數)
  • 在使用者整個會話中保留識別符號的狀態(即在整個會話中公共變數的值一直保留,在一個新的會話中公共變數的值又被初始化)

5、改善效能

  • 包在首次被呼叫時。作為一個整體全部調入記憶體,不必一個過程一個過程調入記憶體。
  • 減少多次調入時的磁碟I/O次數。