oracle 存儲過程 包 【轉】


 

一、為什么要用存儲過程?

如果在應用程序中經常需要執行特定的操作,可以基於這些操作簡歷一個特定的過程。通過使用過程可以簡化客戶端程序的開發和維護,而且還能提高客戶端程序的運行性能。

二、過程的優點?

1、預編譯:存儲過程預先編譯好放在數據庫內,減少編譯語句所花的時間。

2、緩存:預編譯的存儲過程會進入緩存,所以對於經常執行的存儲過程,除了第一次執行外,其它次數的執行速度會明顯提高。

3、減少網絡傳輸:特別是對於一些處理數據的存儲過程,不必像直接使用SQL語句那樣多次傳送數據到客戶端。

4 、可維護性高:更新存儲過程通常要比更改、測試和部署應用程序需要的時間和精力要少。

5、代碼的重用:一個可以重用的存儲過程可以應用到應用程序的多個位置。

6、增強安全性:通過對用戶授權對存儲過程的訪問權限,它們可以提供對特定數據的訪問;提高數據安全性,來防止SQL注入。

三、缺點:

1、如果需要對存儲過程的輸入輸出參數做更改的話,還要更改程序。

2、可移植性差:因為存儲過程將應用程序的業務處理綁定到數據庫中,以此使用存儲過程來處理業務邏輯限制了應用程序的可移植性。

四、創建存儲過程

 1 --1、簡單的存儲過程
 2 create or replace procedure procedure_test
 3 (p_id in varchar,p_status out varchar)  --p_id為輸入參數 ,p_status為輸出參數
 4 as
 5  t_name varchar2(20);
 6  t_count number:=0;
 7 begin
 8  select votetitle,vatesum into t_name,t_count from votemaster where id=p_id; --注意:此處沒有:來賦值
 9  if t_count <=0 then
10      p_status:= t_name||':差';
11  elsif t_count >0 and t_count <3 then
12      p_status:= t_name||':良好';
13  else
14      p_status:= t_name||':優秀';
15  end if;
16 end;
17 --執行
18 declare 
19  out_param varchar2(50);
20 begin 
21  procedure_test('1',out_param);
22   dbms_output.put_line(out_param);
23 end;
24 
25 --2、帶游標的存儲過程
26 create or replace procedure procedure_cursor_test
27 (p_id in varchar2,p_status out varchar2)
28 as
29   vote votemaster%rowtype; --聲明一個對象(votemaster)類型的對象
30   cursor my_cur is select * from votemaster; --聲明一個游標並填充數據
31 begin
32   open my_cur; --打開游標
33        loop
34           fetch my_cur into vote ; --循環游標,並放入對象
35           exit when my_cur%notfound; --如果沒有數據,則直接exit
36           if vote.id=p_id then
37              p_status := vote.votetitle||''||vote.vatesum;
38              --如果想終止循環,可以直接exit;
39           end if;
40        end loop;
41   close my_cur; --關閉游標
42 end;
43 --執行
44 declare 
45  out_param varchar2(50);
46 begin 
47   procedure_cursor_test('1',out_param);
48   dbms_output.put_line(out_param);
49 end;

 

 五、程序包

1、程序包:包是一組相關過程、函數、變量、游標、常量等PL/SQL程序設計元素的組合。它具有面向對象程序設計語言的特點,是對這些PL/SQL程序設計元素的封裝。包類似於C++或Java程序中的類,而變量相當於類中的成員變量,過程和函數相當於方法,把相關的模塊歸類成為包,可使開發人員利用面向對象的方法進行存儲過程的開發,從而提高系統性能。與類相同,包中的程序元素也分為公用元素和私有元素兩種,這兩種元素的區別是他們允許訪問的程序范圍不同,即他們的作用域不同。公用元素不僅可以被包中的函數、過程調用,也可以被包外的PL/SQl塊調用。而私有元素只能被該包內部的函數或過程調用。

2、使用程序包的優點:在PL/SQL設計中,使用包不僅可以使程序模塊化,對外隱藏包內所使用的信息,而寫程序包可以提高程序的運行效率。因為,當程序首次調用程序包內部的函數或過程時,Oracle將整個程序包調入內存,當再次調用程序包中的元素時,Oracle直接從內存中讀取,而不需要進行磁盤的IO操作,從而使程序的執行效率提高。

3、一個程序包分為兩部分組成:

(1)、包定義:包定義部分聲明包內數據類型、變量、常量、游標、子程序和函數等元素,這些元素為包的共有元素。

(2)、包主體:包主題則定義了包定義部分的具體實現,在包主體中還可以聲明和實現私有元素。

 1 --包定義
 2 create or replace package t_package
 3 is
 4   --定義過程
 5   procedure append_proc(t varchar2,a out varchar2);
 6   --過程的重載
 7   procedure append_proc(t number,a out varchar2);
 8   --定義函數
 9   function append_fun(t varchar2) return varchar2;
10   
11 end;
 1 --包主題
 2 create or replace package body t_package
 3 is
 4   v_t varchar2(30);
 5   --私有成員函數
 6   function private_fun(t varchar2) return varchar2 is
 7   begin
 8      v_t := t||'hello';
 9      return v_t;
10   end;
11   --實現過程
12   procedure append_proc(t varchar2,a out varchar2) is
13   begin
14    a := t||'hello'; 
15   end;
16   --過程的重載
17   procedure append_proc(t number,a out varchar2) is 
18   begin 
19     a := t||'hello'; 
20   end;
21   --實現函數
22   function append_fun(t varchar2) 
23   return varchar2 is
24   begin
25      v_t := t||'hello';
26      return v_t;
27   end;
28 end;

http://zxf-noimp.iteye.com/blog/1145442

 

 

 

  1. CREATE OR REPLACE PROCEDURE testp(p_value IN VARCHAR2)  
  2.        IS  
  3.     TYPE ref_cursor_type IS REF CURSOR--定義一個動態游標  
  4.     users ref_cursor_type;   --定義游標類型  
  5.     user Users%ROWTYPE; --定義變量類型  
  6.     vSql VARCHAR2(255);  
  7. BEGIN  
  8.   vSql := 'select * from Users'--要查詢的sql字符串,可拼接起來  
  9.   OPEN users FOR vSql;  --打開游標  
  10.   LOOP  
  11.     FETCH users INTO users; --循環遍歷users列表給user,user為臨時對象  
  12.     exit when bills%notfound;   
  13.     -- user相當於表對象可以直接拿來用  
  14.     --比如要打印user對象里面的name  
  15.     dbms_outpt.put_line(user.name);  
  16.   end loop;  
  17.   CLOSE bills;  
  18. END;  

 

 

 

 1 CREATE OR REPLACE PROCEDURE PRODUCT_TEMP_UPDATE_PRC AS  --第1行表示創建存儲過程,名稱為PRODUCT_TEMP_UPDATE_PRC 。
 2   PC_DELESTR   VARCHAR2(50); --刪除臨時表記錄語句            第2~7行表示聲明變量。
 3   PC_CREATESTR VARCHAR2(500); --創建臨時表
 4   TABEXT       VARCHAR2(10); --用於判斷臨時表是否存在中間變量
 5 
 6   CUR_CTGY   PRODUCTINFO.CATEGORY%TYPE;
 7   CUR_PRTIFO PRODUCTINFO%ROWTYPE;
 8                                                         --第9~11行表示創建游標cur_category;
 9   CURSOR CUR_CATEGORY --產品表中的  產品類型  游標
10   IS
11     SELECT CATEGORY FROM PRODUCTINFO GROUP BY CATEGORY;
12  --第13~19行表示創建游標CUR_PROINFO;該游標帶有參數,其參數代表產品類型的編碼。游標根據產品的類型不同,獲取產品類型中價格最低的數據。
13   CURSOR CUR_PROINFO(CTGY VARCHAR) IS
14     SELECT *
15       FROM (SELECT *
16               FROM PRODUCTINFO
17              WHERE CATEGORY = CTGY
18              ORDER BY PRODUCTPRICE ASC)
19      WHERE ROWNUM < 2;
20 
21 BEGIN
22   SELECT COUNT(1)--第22~25表示判斷臨時表productinfo_tmp是否存在。此處利用select into語句把結果放到變量tabext中,如果該表存在結果為1,否則為0.tabext變量將在第37行使用。
23     INTO TABEXT
24     FROM ALL_TABLES
25    WHERE TABLE_NAME = 'productinfo_tmp';
26 
27   PC_DELESTR   := 'delete from productinfo_tmp';
28   PC_CREATESTR := 'create global temporary table productinfo_tmp
29   (productid varchar2(10) not null,
30   productname varchar2 (20),
31   productprice number(8,2),
32   quantity number(10),
33   category varchar2(10),
34   desperaction varchar2(1000),
35   origin varchar2(10))on commit preserve rows';
36 --第37~44行完成分析步驟中的第一步:創建臨時表productinfo_tmp。首先判斷臨時表是否存在,如果不存在,則創建,如果存在則刪除表中數據。這里使用了execute immediate語句,利用它執行DDL語句及動態語句。
37   IF TABEXT = 0 THEN
38     --不存在臨時表就創建一個
39     EXECUTE IMMEDIATE PC_CREATESTR;
40     DBMS_OUTPUT.PUT_LINE('創建臨時表成功!');
41   ELSE
42     EXECUTE IMMEDIATE PC_DELESTR;
43     DBMS_OUTPUT.PUT_LINE('刪除記錄完成!');
44   END IF;
45   OPEN CUR_CATEGORY;--第45~49行表示打開游標cur_category(產品類型  游標),並進入流循環取值。當游標的%nofound屬性為true時退出。
46   LOOP
47     FETCH CUR_CATEGORY
48       INTO CUR_CTGY;
49     EXIT WHEN CUR_CATEGORY%NOTFOUND;
50     OPEN CUR_PROINFO(CUR_CTGY);--第50~53行表示打開游標cur_proinfo,它的參數是cur_category中的結果。
51     FETCH CUR_PROINFO
52       INTO CUR_PRTIFO;
53     IF CUR_PROINFO%FOUND THEN
54       IF CUR_PRTIFO.PRODUCTPRICE < 20 THEN--第54~58行表示判斷價格是否低於20,如果低於20輸出到屏幕。
55         ---產品價格低於20
56         DBMS_OUTPUT.PUT_LINE('產品ID' || CUR_PRTIFO.PRODUCTID || '產品名稱' ||
57                              CUR_PRTIFO.PRODUCTNAME || '產品價格' ||
58                              CUR_PRTIFO.PRODUCTPRICE);
59       ELSE
60         --非低於20價格的產品輸入到臨時表productinfo_tmp            第60~69行表示如果非低於20的插入表productinfo_tmp中。
61         EXECUTE IMMEDIATE 'insert into productinfo_tmp(
62         productid,productname,productprice,quantity,category,desperaction,origin) values
63         (''' || CUR_PRTIFO.PRODUCTID || ''',''' ||
64                           CUR_PRTIFO.PRODUCTNAME || ''',''' ||
65                           CUR_PRTIFO.PRODUCTPRICE || ''',''' ||
66                           CUR_PRTIFO.QUANTITY || ''',''' ||
67                           CUR_PRTIFO.CATEGORY || ''',''' ||
68                           CUR_PRTIFO.DESPERACTION || ''',''' ||
69                           CUR_PRTIFO.ORIGIN || ''')';
70       END IF;
71     END IF;
72     CLOSE CUR_PROINFO;
73   END LOOP;
74   COMMIT;
75   CLOSE CUR_CATEGORY;
76   EXECUTE IMMEDIATE 'update productinfo_tmp set desperaction = ''熱銷產品''';--第76行表示將productinfo_tmp表中的數據修改為熱銷產品。
77 END;

【執行】

SQL>exec PRODUCT_TEMP_UPDATE_PRC ;

轉自:http://www.cnblogs.com/Rainbow-G/articles/4301131.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM