.Net 5的控制檯程式中使用桌面類庫
1. 程式包的概念
1.程式包定義
程式包用於將邏輯相關的PL/SQL塊或元素(變數、常量、過程、函式等)組織在一起,作為一個完整的單元儲存在資料庫中,用包名稱來標識程式包。程式包類似於面向物件中的類。
2.程式包的結構
3.包中可以包含的元素的性質
元素的性質 |
描述 |
在包中的位置 |
公共的(public) |
在整個應用的全過程均有效 |
包的說明部分說明 |
私有的(private) |
對包以外的過程和函式是不可見的 |
在包體部分說明和定義 |
區域性的 |
只在一個過程或函式內使用 |
在所屬過程或函式的內部說明和定義 |
2. 建立包頭
1.建立包頭的命令格式:
CREATE [OR REPLACE] PACKAGE <packagename> IS|AS 公共資料型別和物件宣告; 公共子程式和函式說明; END [<資料包名稱>];
說明:
- 在包頭中宣告的元素(過程、函式、變數等)是公共元素,只在包體中宣告的元素是私有元素。
- 公共元素可以在包的外面單獨呼叫,但私有元素只能在包體內定義別的過程函式時被呼叫。
- 區域性變數是在包體內過程或函式中定義的變數,該區域性變數只能在該過程函式內使用,不能在包體內別的過程函式內使用。
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 REPLACEPACKAGE 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次數。