ORACLE PL/SQ入門 存儲過程

  1. ORACLE PL/SQ入門(六-九、存儲過程、函數、觸發器、包)
  2. ORACLE PL/SQ入門 
  3. 六、存儲過程
  4. 1.命令格式
  5.   存儲過程是一個PL/SQL程序塊,接受零個或多個參數作爲輸入(INPUT)或輸出(OUTPUT)、或既作輸入又作輸出(INOUT),與函數不同, 存儲過程沒有返回值,存儲過程不能由SQL語句直接使用,只能通過EXECUT命令或PL/SQL程序塊內部調用,定義存儲過程的語法如下:
  6. PROCEDURE Name [(Parameter[,Parameter,])]
  7. IS|AS
  8.   [Local Declarations]
  9. BEGIN
  10.   Execute statements;
  11.   [EXCEPTION Exception Handlers]
  12. END [Name];
  13. 2.調用
  14.   存儲過程可以直接用EXECUT命令調用或PL/SQL程序塊內部調用。用EXECUT命令調用存儲過程的格式如下:
  15. SQL>EXCUTE  Proc_Name(par1, par2…);
  16.   存儲過程也可以被另外的PL/SQL塊調用,調用的語句是:
  17. DECLARE par1, par2;
  18. BEGIN
  19.   Proc_Name(par1, par2…);
  20. END;
  21. 3.釋放
  22.   當某個存儲過程不再需要時,應將其從內存中刪除,以釋放它佔用的內存資源。釋放過程的語句格式如下:
  23. SQL>DROP PROCEDURE Proc_Name;
  24. 4.實例:
  25.   編寫存儲過程,顯示所指定僱員名所在的部門名和位置。
  26. CREATE OR REPLACE PROCEDURE DeptMesg(pename emp.ename%TYPE,
  27.                                      pdname OUT dept.dname%TYPE,
  28.                                      ploc   OUT dept.loc%TYPE) AS
  29. BEGIN
  30.   SELECT dname, loc
  31.     INTO pdname, ploc
  32.     FROM emp, dept
  33.    WHERE emp.deptno = dept.deptno
  34.      AND emp.ename = pename;
  35. END;
  36.   調用:
  37. VARIABLE vdname VARCHAR2(14);
  38. VARIABLE vloc VARCHAR2(13);
  39. EXECUTE DeptMesg('SMITH', :vdname£? :vloc);
  40. PRINT vdname vloc; 
  41. 七、函數
  42. 1.命令格式
  43.   函數是命名了的、存儲在數據庫中的PL/SQL程序塊。函數接受零個或多個輸入參數,有一個返回值,返回值的數據類型在創建函數時定義。定義函數的語法如下:
  44. FUNCTION Name [{Parameter[,Parameter,])]
  45. RETURN DataTypes
  46. IS
  47. [Local Declarations]
  48. BEGIN
  49.   Execute Statements;
  50.   [EXCEPTION Exception Handlers]
  51. END [Name];
  52. 2.調用
  53.   無論在命令行還是在程序語句中,函數都可以通過函數名稱直接在表達式中調用。例如:將函數Count_Num(‘女’)的返回值賦予變量Man_Num。
  54. SQL>EXECUTE Man_Num := Count_Num('女');
  55. 3.釋放
  56.   當函數不再使用時,要用DROP命令將其從內存中刪除,例如:
  57. SQL>DROP FUNCTION Count_Num;
  58. 4.實例
  59.   編寫一個函數以顯示該僱員在此組織中的工作天數。
  60. CREATE OR REPLACE FUNCTION Hire_Day(no emp.empno%TYPE) RETURN NUMBER AS
  61.   vhiredate emp.hiredate%TYPE;
  62.   vday      NUMBER;
  63. BEGIN
  64.   SELECT hiredate INTO vhiredate FROM emp WHERE empno = no;
  65.   vday := CEIL(SYSDATE - vhiredate);
  66.   RETURN vday;
  67. END;
  68. 八、觸發器
  69. 1.觸發器的創建規則:
  70.   ①作用範圍清晰;
  71.   ②不要讓觸發器去完成Oracle後臺已經能夠完成的功能;
  72.   ③限制觸發器代碼的行數;
  73.   ④不要創建遞歸的觸發器;
  74.   ⑤觸發器僅在被觸發語句觸發時進行集中的,全局的操作,同用戶和數據庫應用無關。
  75. 2.可以創建被如下語句所觸發的觸發器:
  76.   ①DML語句(DELETE,INSERT,UPDATE);
  77.   ②DDL語句(CREATE,ALTER, DROP);
  78.   ③數據庫操作(SERVERERROR,LOGON,LOGOFF,STARTUP,SHUTDOWN)。 
  79. 3.注意事項
  80.   ①觸發器可以聲明爲在對記錄進行操作之前,在之前(檢查約束之前和 INSERT,UPDATE 或 DELETE 執行前)或之後(在檢查約束之後和完成 INSERT, UPDATE 或 DELETE 操作)觸發;
  81.   ②一個 FOR EACH ROW 執行指定操作的觸發器爲操作修改的每一行都調用一次;
  82.   ③SELECT 並不更改任何行,因此不能創建 SELECT 觸發器.這種場合下規則和視圖更適合;
  83.   ④觸發器和某一指定的表格有關,當該表格備刪除時,任何與該表有關的觸發器同樣會被刪除;
  84.   ⑤在一個表上的每一個動作只能有一個觸發器與之關聯;
  85.   ⑥在一個單獨的表上,最多隻能創建三個觸發器與之關聯,一個INSERT觸發器,一個DELETE觸發器和一個UPDATE觸發器;
  86. 4.刪除觸發器的語句格式爲:
  87. DROP TRIGGER name ON table;
  88.   一個觸發器由三部分組成:觸發事件或語句、觸發限制和觸發器動作。觸發事件或語句是指引起激發觸發器的SQL語句,可爲對一指定表的INSERT、UNPDATE或DELETE語句。觸發限制是指定一個布爾表達式,當觸發器激發時該布爾表達式是必須爲真。觸發器作爲過程,是PL/SQL塊,當觸發語句發出、觸發限制計算爲真時該過程被執行。
  89. 5.實例
  90.   編寫一個數據庫觸發器,當任何時候某個部門從dept表中刪除時,該觸發器將從emp表中刪除該部門的所有僱員。
  91. CREATE OR REPLACE TRIGGER del_emp_deptno
  92.   BEFORE DELETE ON dept
  93.   FOR EACH ROW
  94. BEGIN
  95.   DELETE FROM emp WHERE deptno = :OLD.deptno;
  96. END;
  97. 九、包
  98. 1.包頭
  99.   創建包頭的語句格式如下:
  100.   CREATE PACKAGE<包名> IS
  101.     變量、常量及數據類型定義;
  102.     遊標定義;
  103.     函數、過程定義和參數列表及返回類型;
  104.   END<包名>;
  105. 2.包體
  106.   創建包主體部分的語句格式如下:
  107.   CREATE PACKAGE BODY<包名>
  108.   AS
  109.     遊標、函數、過程的具體定義;
  110.   END<包名>;
  111. 3.實例
  112.   包頭代碼:
  113. --創建包頭
  114. CREATE PACKAGE test_package IS
  115.   --定義變量
  116.   man_num   NUMBER;
  117.   woman_num NUMBER;
  118.   --定義遊標
  119.   CURSOR學生;
  120.   --定義函數
  121.   CREATE FUNCTION f_count(in sex IN 學生.sex%TYPE)
  122.   --定義返回值類型
  123.   RETURN NUMBER;
  124.   --定義過程
  125.   CREATE PROCEDURE p_count(in_sex IN 學生.sex%TYPE, out_num OUT NUMBER);
  126. --包頭結束
  127. END test_package;
  128.   包體代碼:
  129. --創建包體
  130. CREATE PACKAGE BODY test_package AS
  131.   --遊標具體定義
  132.   CURSOR 學生IS
  133.     SELECT 學號,姓名 FROM 學生 WHERE 學號 < 50;
  134.   --函數具體定義
  135.   FUNCTION f_count(in_sex IN學生.sex%TYPE)
  136.   --定義返回值類型
  137.    RETURN NUMBER IS
  138.     out_num NUMBER;
  139.     --函數體
  140.   BEGIN
  141.     IF in_sex = '男' THEN
  142.       SELECT count(sex) INTO out_num FROM 學生 WHERE性別='男';
  143.     ELSE
  144.       SELECT count(sex) INTO out_num FROM 學生 WHERE 性別='女';
  145.     END IF;
  146.     --返回函數值
  147.     RETURN(out_num);
  148.     --函數定義結束
  149.   END f_count;
  150.   --過程具體定義
  151.   PROCEDURE p_count(in_sex IN學生.sex%TYPE, out_num OUT NUMBER) AS
  152.     --過程體
  153.   BEGIN
  154.     IF in_sex = '男' THEN
  155.       SELECT count(sex) INTO out_num FROM 學生 WHERE性別 = '男';
  156.     ELSE
  157.       SELECT count(sex) INTO out_num FROM 學生 WHERE 性別= '女';
  158.     END IF;
  159.     --過程定義結束
  160.   END P_count;
  161. --包體定義結束
  162. END test_package; 
  163. oracle 分頁存儲過程
  164. 包頭:
  165. create or replace package JT_P_page is
  166.   -- Author : ujnjt
  167.   -- Created : 2007-8-5 16:43:50
  168.   -- Purpose : 分頁功能
  169.   -- Public type declarations
  170.   type type_cur is ref cursor; --定義遊標變量用於返回記錄集
  171.   procedure Pagination(Pindex in number, --要顯示的頁數索引,從0開始
  172.                        Psql in varchar2, --產生分頁數據的查詢語句
  173.                        Psize in number, --每頁顯示記錄數
  174.                        Pcount out number, --返回的分頁數
  175.                        Prowcount out number, --返回的記錄數
  176.                        v_cur out type_cur --返回分頁數據的遊標
  177.                        );
  178. end JT_P_page;
  179. 包體:
  180. create or replace package body JT_P_page is
  181.   procedure Pagination(Pindex in number, --要顯示的頁數索引,從0開始
  182.                        Psql in varchar2, --產生分頁數據的查詢語句
  183.                        Psize in number, --每頁顯示記錄數
  184.                        Pcount out number, --返回的分頁數
  185.                        Prowcount out number, --返回的記錄數
  186.                        v_cur out type_cur --返回分頁數據的遊標
  187.                        ) AS
  188.     v_sql VARCHAR2(1000);
  189.     v_Pbegin number;
  190.     v_Pend number;
  191.   begin
  192.     v_sql := 'select count(*) from (' || Psql || ')';
  193.     execute immediate v_sql into Prowcount; --計算記錄總數
  194.     Pcount := ceil(Prowcount / Psize); --計算分頁總數
  195.     --顯示任意頁內容
  196.     v_Pend := Pindex * Psize + Psize;
  197.     v_Pbegin := v_Pend - Psize + 1;
  198.   
  199.     --Psql := 'select rownum as rn , t.* from pay_en_voucher t'; --要求必須包含rownum字段
  200.     v_sql := 'select * from (' || Psql || ') where rn between ' || v_Pbegin || ' and ' || v_Pend;
  201.              
  202.     open v_cur for v_sql;
  203.   end Pagination;
  204.   
  205. end JT_P_page;
  206. 調用方法:
  207. -- Created on 2007-8-5 by ujnjt 
  208. declare
  209.   psqlContent varchar2(1000);
  210.   pageIndex number;
  211.   pageCount number; --返回的分頁數
  212.   pageSize number; --每一頁的記錄數
  213.   rowscount number; -- 返回的記錄總數
  214.   return_cur JT_P_PAGE.type_cur;
  215.   curr_id pay_en_voucher.id%type;
  216.   curr_rn number;
  217. begin
  218.   psqlContent := 'select rownum as rn , t.id from pay_en_voucher t';
  219.   pageIndex := 0;
  220.   pageSize := 20;
  221.   JT_P_PAGE.Pagination(pageIndex,
  222.                        psqlContent,
  223.                        pageSize,
  224.                        pageCount,
  225.                        rowscount,
  226.                        return_cur);
  227.   if return_cur%isopen then
  228.     close return_cur;
  229.   end if;
  230.   
  231.   for Counter in 0 .. pageCount - 1 loop
  232.   pageIndex := Counter;
  233.   JT_P_PAGE.Pagination(pageIndex, psqlContent, pageSize, pageCount, rowscount, return_cur);
  234.   if return_cur%isopen then
  235.     dbms_output.put_line('第' || (pageIndex + 1) || '頁數據開始');
  236.     loop
  237.       fetch return_cur
  238.         into curr_rn, curr_id;
  239.       if (return_cur%notfound) then
  240.         exit;
  241.       end if;
  242.       dbms_output.put_line(curr_rn);
  243.       dbms_output.put_line(curr_id);
  244.       dbms_output.put_line('--------');
  245.     end loop;
  246.     dbms_output.put_line('第' || (pageIndex + 1) || '頁數據結束');
  247.     close return_cur;
  248.     dbms_output.put_line('=========================================');
  249.   end if;
  250. end loop;
  251. end;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章