- ORACLE PL/SQ入門(六-九、存儲過程、函數、觸發器、包)
- ORACLE PL/SQ入門
- 六、存儲過程
- 1.命令格式
- 存儲過程是一個PL/SQL程序塊,接受零個或多個參數作爲輸入(INPUT)或輸出(OUTPUT)、或既作輸入又作輸出(INOUT),與函數不同, 存儲過程沒有返回值,存儲過程不能由SQL語句直接使用,只能通過EXECUT命令或PL/SQL程序塊內部調用,定義存儲過程的語法如下:
- PROCEDURE Name [(Parameter[,Parameter,])]
- IS|AS
- [Local Declarations]
- BEGIN
- Execute statements;
- [EXCEPTION Exception Handlers]
- END [Name];
- 2.調用
- 存儲過程可以直接用EXECUT命令調用或PL/SQL程序塊內部調用。用EXECUT命令調用存儲過程的格式如下:
- SQL>EXCUTE Proc_Name(par1, par2…);
- 存儲過程也可以被另外的PL/SQL塊調用,調用的語句是:
- DECLARE par1, par2;
- BEGIN
- Proc_Name(par1, par2…);
- END;
- 3.釋放
- 當某個存儲過程不再需要時,應將其從內存中刪除,以釋放它佔用的內存資源。釋放過程的語句格式如下:
- SQL>DROP PROCEDURE Proc_Name;
- 4.實例:
- 編寫存儲過程,顯示所指定僱員名所在的部門名和位置。
- CREATE OR REPLACE PROCEDURE DeptMesg(pename emp.ename%TYPE,
- pdname OUT dept.dname%TYPE,
- ploc OUT dept.loc%TYPE) AS
- BEGIN
- SELECT dname, loc
- INTO pdname, ploc
- FROM emp, dept
- WHERE emp.deptno = dept.deptno
- AND emp.ename = pename;
- END;
- 調用:
- VARIABLE vdname VARCHAR2(14);
- VARIABLE vloc VARCHAR2(13);
- EXECUTE DeptMesg('SMITH', :vdname£? :vloc);
- PRINT vdname vloc;
- 七、函數
- 1.命令格式
- 函數是命名了的、存儲在數據庫中的PL/SQL程序塊。函數接受零個或多個輸入參數,有一個返回值,返回值的數據類型在創建函數時定義。定義函數的語法如下:
- FUNCTION Name [{Parameter[,Parameter,])]
- RETURN DataTypes
- IS
- [Local Declarations]
- BEGIN
- Execute Statements;
- [EXCEPTION Exception Handlers]
- END [Name];
- 2.調用
- 無論在命令行還是在程序語句中,函數都可以通過函數名稱直接在表達式中調用。例如:將函數Count_Num(‘女’)的返回值賦予變量Man_Num。
- SQL>EXECUTE Man_Num := Count_Num('女');
- 3.釋放
- 當函數不再使用時,要用DROP命令將其從內存中刪除,例如:
- SQL>DROP FUNCTION Count_Num;
- 4.實例
- 編寫一個函數以顯示該僱員在此組織中的工作天數。
- CREATE OR REPLACE FUNCTION Hire_Day(no emp.empno%TYPE) RETURN NUMBER AS
- vhiredate emp.hiredate%TYPE;
- vday NUMBER;
- BEGIN
- SELECT hiredate INTO vhiredate FROM emp WHERE empno = no;
- vday := CEIL(SYSDATE - vhiredate);
- RETURN vday;
- END;
- 八、觸發器
- 1.觸發器的創建規則:
- ①作用範圍清晰;
- ②不要讓觸發器去完成Oracle後臺已經能夠完成的功能;
- ③限制觸發器代碼的行數;
- ④不要創建遞歸的觸發器;
- ⑤觸發器僅在被觸發語句觸發時進行集中的,全局的操作,同用戶和數據庫應用無關。
- 2.可以創建被如下語句所觸發的觸發器:
- ①DML語句(DELETE,INSERT,UPDATE);
- ②DDL語句(CREATE,ALTER, DROP);
- ③數據庫操作(SERVERERROR,LOGON,LOGOFF,STARTUP,SHUTDOWN)。
- 3.注意事項
- ①觸發器可以聲明爲在對記錄進行操作之前,在之前(檢查約束之前和 INSERT,UPDATE 或 DELETE 執行前)或之後(在檢查約束之後和完成 INSERT, UPDATE 或 DELETE 操作)觸發;
- ②一個 FOR EACH ROW 執行指定操作的觸發器爲操作修改的每一行都調用一次;
- ③SELECT 並不更改任何行,因此不能創建 SELECT 觸發器.這種場合下規則和視圖更適合;
- ④觸發器和某一指定的表格有關,當該表格備刪除時,任何與該表有關的觸發器同樣會被刪除;
- ⑤在一個表上的每一個動作只能有一個觸發器與之關聯;
- ⑥在一個單獨的表上,最多隻能創建三個觸發器與之關聯,一個INSERT觸發器,一個DELETE觸發器和一個UPDATE觸發器;
- 4.刪除觸發器的語句格式爲:
- DROP TRIGGER name ON table;
- 一個觸發器由三部分組成:觸發事件或語句、觸發限制和觸發器動作。觸發事件或語句是指引起激發觸發器的SQL語句,可爲對一指定表的INSERT、UNPDATE或DELETE語句。觸發限制是指定一個布爾表達式,當觸發器激發時該布爾表達式是必須爲真。觸發器作爲過程,是PL/SQL塊,當觸發語句發出、觸發限制計算爲真時該過程被執行。
- 5.實例
- 編寫一個數據庫觸發器,當任何時候某個部門從dept表中刪除時,該觸發器將從emp表中刪除該部門的所有僱員。
- CREATE OR REPLACE TRIGGER del_emp_deptno
- BEFORE DELETE ON dept
- FOR EACH ROW
- BEGIN
- DELETE FROM emp WHERE deptno = :OLD.deptno;
- END;
- 九、包
- 1.包頭
- 創建包頭的語句格式如下:
- CREATE PACKAGE<包名> IS
- 變量、常量及數據類型定義;
- 遊標定義;
- 函數、過程定義和參數列表及返回類型;
- END<包名>;
- 2.包體
- 創建包主體部分的語句格式如下:
- CREATE PACKAGE BODY<包名>
- AS
- 遊標、函數、過程的具體定義;
- END<包名>;
- 3.實例
- 包頭代碼:
- --創建包頭
- CREATE PACKAGE test_package IS
- --定義變量
- man_num NUMBER;
- woman_num NUMBER;
- --定義遊標
- CURSOR學生;
- --定義函數
- CREATE FUNCTION f_count(in sex IN 學生.sex%TYPE)
- --定義返回值類型
- RETURN NUMBER;
- --定義過程
- CREATE PROCEDURE p_count(in_sex IN 學生.sex%TYPE, out_num OUT NUMBER);
- --包頭結束
- END test_package;
- 包體代碼:
- --創建包體
- CREATE PACKAGE BODY test_package AS
- --遊標具體定義
- CURSOR 學生IS
- SELECT 學號,姓名 FROM 學生 WHERE 學號 < 50;
- --函數具體定義
- FUNCTION f_count(in_sex IN學生.sex%TYPE)
- --定義返回值類型
- RETURN NUMBER IS
- out_num NUMBER;
- --函數體
- BEGIN
- IF in_sex = '男' THEN
- SELECT count(sex) INTO out_num FROM 學生 WHERE性別='男';
- ELSE
- SELECT count(sex) INTO out_num FROM 學生 WHERE 性別='女';
- END IF;
- --返回函數值
- RETURN(out_num);
- --函數定義結束
- END f_count;
- --過程具體定義
- PROCEDURE p_count(in_sex IN學生.sex%TYPE, out_num OUT NUMBER) AS
- --過程體
- BEGIN
- IF in_sex = '男' THEN
- SELECT count(sex) INTO out_num FROM 學生 WHERE性別 = '男';
- ELSE
- SELECT count(sex) INTO out_num FROM 學生 WHERE 性別= '女';
- END IF;
- --過程定義結束
- END P_count;
- --包體定義結束
- END test_package;
- oracle 分頁存儲過程
- 包頭:
- create or replace package JT_P_page is
- -- Author : ujnjt
- -- Created : 2007-8-5 16:43:50
- -- Purpose : 分頁功能
- -- Public type declarations
- type type_cur is ref cursor; --定義遊標變量用於返回記錄集
- procedure Pagination(Pindex in number, --要顯示的頁數索引,從0開始
- Psql in varchar2, --產生分頁數據的查詢語句
- Psize in number, --每頁顯示記錄數
- Pcount out number, --返回的分頁數
- Prowcount out number, --返回的記錄數
- v_cur out type_cur --返回分頁數據的遊標
- );
- end JT_P_page;
- 包體:
- create or replace package body JT_P_page is
- procedure Pagination(Pindex in number, --要顯示的頁數索引,從0開始
- Psql in varchar2, --產生分頁數據的查詢語句
- Psize in number, --每頁顯示記錄數
- Pcount out number, --返回的分頁數
- Prowcount out number, --返回的記錄數
- v_cur out type_cur --返回分頁數據的遊標
- ) AS
- v_sql VARCHAR2(1000);
- v_Pbegin number;
- v_Pend number;
- begin
- v_sql := 'select count(*) from (' || Psql || ')';
- execute immediate v_sql into Prowcount; --計算記錄總數
- Pcount := ceil(Prowcount / Psize); --計算分頁總數
- --顯示任意頁內容
- v_Pend := Pindex * Psize + Psize;
- v_Pbegin := v_Pend - Psize + 1;
- --Psql := 'select rownum as rn , t.* from pay_en_voucher t'; --要求必須包含rownum字段
- v_sql := 'select * from (' || Psql || ') where rn between ' || v_Pbegin || ' and ' || v_Pend;
- open v_cur for v_sql;
- end Pagination;
- end JT_P_page;
- 調用方法:
- -- Created on 2007-8-5 by ujnjt
- declare
- psqlContent varchar2(1000);
- pageIndex number;
- pageCount number; --返回的分頁數
- pageSize number; --每一頁的記錄數
- rowscount number; -- 返回的記錄總數
- return_cur JT_P_PAGE.type_cur;
- curr_id pay_en_voucher.id%type;
- curr_rn number;
- begin
- psqlContent := 'select rownum as rn , t.id from pay_en_voucher t';
- pageIndex := 0;
- pageSize := 20;
- JT_P_PAGE.Pagination(pageIndex,
- psqlContent,
- pageSize,
- pageCount,
- rowscount,
- return_cur);
- if return_cur%isopen then
- close return_cur;
- end if;
- for Counter in 0 .. pageCount - 1 loop
- pageIndex := Counter;
- JT_P_PAGE.Pagination(pageIndex, psqlContent, pageSize, pageCount, rowscount, return_cur);
- if return_cur%isopen then
- dbms_output.put_line('第' || (pageIndex + 1) || '頁數據開始');
- loop
- fetch return_cur
- into curr_rn, curr_id;
- if (return_cur%notfound) then
- exit;
- end if;
- dbms_output.put_line(curr_rn);
- dbms_output.put_line(curr_id);
- dbms_output.put_line('--------');
- end loop;
- dbms_output.put_line('第' || (pageIndex + 1) || '頁數據結束');
- close return_cur;
- dbms_output.put_line('=========================================');
- end if;
- end loop;
- end;
ORACLE PL/SQ入門 存儲過程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.