快速上手Oracle 存儲過程、自定義函數

ORACLE 存儲過程語法

CREATE [OR REPLACE] PROCEDURE [schema.] procedure_name 
[parameter_name] [[IN] datatype [{:=|DEFAULT} expression] 
| {OUT | IN OUT} [NOCOPY] datatype][,...]{IS | AS} BODY;

執行無參數的存儲過程

EXEC procedure_name;sql

執行有參數的存儲過程

EXEC procedure_name(parameters);數據庫

若是存儲過程當中有輸出語句,須要設置SERVEROUTPUT的輸出狀態

SHOW SERVEROUTPUT -- 查看
SET SERVEROUTPUT ON -- 開啓

建立無參數的存儲過程

  • 修改READERINFO2表中BOOKCOUNT的數據,爲計算機系可借書的數目增長1
CREATE PROCEDURE PRO_READER
AS

BEGIN
UPDATE READERINFO2 SET BOOKCOUNT = BOOKCOUNT+1
WHERE UNIT = '計算機系';
END;

在存儲過程當中使用遊標

  • 搜索READERINFO2表中全部自動化系和生物系的數據,並判斷當借書的數據(BOOKCOUNT)小於3時,爲其增長1
CREATE PROCEDURE PRO_READER_COT
AS
	v_readerinfo READERINFO2%ROWTYPE;-- 聲明標變量v_readerinfo,其數據類型爲READERINFO2行記錄類型

	CURSOR cursor_readerinfo
	IS 
	SELECT *
	FROM READERINFO2
	WHER UNIT IN('自動化系','生物系')
	ORDER BY UNIT;-- 表示聲明建立遊標cursor_readerinfo

	BEGIN
		OPE cursor_readerinfo; --打開遊標
		LOOP
			FETCH cursor_readerinfo INTO v_readerinfo; -- 從遊標中提取指針指向當前行數據,並存入標量v_readerinfo
			EXIT WHEN cursor_readerinfo%NOTFOUND; -- 表示進行判斷,當遊標指針到尾部時,將結束循環
			IF v_readerinfo.bookcount < 3 THEN
				UPDATE READERINFO2 SET BOOKCOUNT = BOOKCOUNT+1
				WHERE READERID = v_readerinfo.readerid;
			END IF;
		END LOOP;
	END;

在存儲過程當中建立表

  • 要求在存儲過程當中建立一個表用於存儲臨時數據
CREATE PROCEDURE PRO_CRTTAB
AS
tabeexists VARCHAR2(2); -- 聲明變量
my_createtab VARCHAR2(400);

BEGIN 
    SELECT COUNT(1) INTO tabeexists
    FROM ALL_TABLES
    WHERE TABLE_NAME = 'MY_TEST_TAB';-- 從ALL_TABLES數據字典中查詢是否已經存在臨時表MY_TEST_TAB,並把結果賦值給變量tabeexists

    my_createtab := 'CREATE GLOBAL TEMPORARY TABLE MY_TEST_TAB
     (TEST VARCHAR2(20) not null)
      ON Commit Preserve Rows';-- 表示變量my_createtab賦值建立臨時表的語句
    
    IF tabeexists = 0 THEN 
        EXECUTE IMMEDIATE my_createtab;
        DBMS_OUTPUT.PUT_LINE('臨時表建立成功...');
    ELSE
        EXECUTE IMMEDIATE 'DELETE FROM MY_TEST_TAB';
        DBMS_OUTPUT.PUT_LINE('記錄已經刪除...');
    END IF;
END;

使用GRANT CREATE ANY TABLE TO <USER>爲用戶賦予權限express

帶有參數的存儲過程

在調用時,經過制定所須要的參數值,實現特定的功能。在建立時,還能夠爲參數制定默認值。存儲過程一旦使用了參數,那麼在執行存儲過程時則要求必須爲其制定參數,參數容許是常量、變量、表達式等。微信

存儲過程的參數有輸入、輸出、輸入輸出3中類型。其中輸入參數也是默認的參數,也叫IN類型參數。oracle

  • 要求建立一個存儲過程,用於查詢READERINFO表中全部READERID、READENAME、UNIT、BOOKCOUNT,以及其在BOOKINFO表中借閱的圖書數目。經過設置輸入參數,使得存儲過程可以靈活地選擇要查詢的讀者單位,以及可以借閱的最少讀書數目,並輸出到屏幕。
CREATE PROCEDURE 
    PRO_READERLIST_SE(unit IN VARCHAR2, minbookcount IN NUMBER)-- 兩個輸入型參數 unit minbookcount
AS 

TYPE reader_book_rc IS RECORD
(
    v_readerid READERINFO.READERID%TYPE,
    v_readername READERINFO.READERNAME%TYPE,
    v_unit READERINFO.UNIT%TYPE,
    v_bookcount READERINFO.BOOKCOUNT%TYPE,
    v_count_reader NUMBER(8)
);                      -- 聲明一個記錄類型的數據類型

v_readebook_rc reader_book_rc;-- 聲明變量 該變量爲記錄類型

CURSOR cur_readebook
IS 
SELECT R.readerid, R.readername, R.unit, R.bookcount, Count(B.reader)borrowedbooks
    FROM ReaderInfo R
    LEFT OUTER JOIN BookInfo B 
    ON R.readerid=B.reader
    WHERE R.unit like unit
    AND R.bookcount >= minbookcount
    GROUP BY R.readerid, R.readerid, R.readername, R.unit, R.bookcount
    ORDER BY R.bookcount;-- 建立遊標,該遊標關聯的查詢語句有條件,該條件來自於該存儲過程的輸入類型參數

BEGIN 
OPEN cur_readebook;

    LOOP
        FETCH cur_readebook INTO v_readebook_rc;
        EXIT WHEN cur_readebook %NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(v_readebook_rc.v_readerid 
        ||'-'|| v_readebook_rc.v_readername
        ||'-'|| v_readebook_rc v_unit
        ||'-'|| v_readebook_rc v_bookcount
        ||'-'|| v_readebook_rc v_count_reader);
    END LOOP; -- 利用循環遍歷遊標,把變量中的數據取出並輸出到屏幕
CLOSE cur_readebook;
end;

調用存儲過程
EXEC PRO_READERLIST_SE('%', 3)函數

爲minbookcount設定默認值指針

CREATE PROCEDURE 
    PRO_READERLIST_SE(unit IN VARCHAR2, minbookcount IN NUMBER DEFAULT 2)
--後面的省略 同上腳本

帶有輸出參數的存儲過程的調用

  • 要求建立一個帶有輸出參數的存儲過程,而後調用它爲變量賦值。
  1. 建立帶有輸出參數的存儲過程。設置存儲過程 PRO_OUT_ELT,該存儲過程電郵一個輸出參數,它的功能是返回輸出參數的值。
CREATE PROCEDURE PRO_OUT_ELT(parm_out OUT VARCHAR2)
AS 
BEGIN
    parm_out := '計算機系';
END;
/
  1. 調用PRO_OUT_ELT存儲過程爲變量賦值。建立存儲過程 PRO_READER_CLOSE,在該存儲過程當中調用PRO_OUT_ELT爲變量賦值。
CREATE PROCEDURE PRO_READER_CLOSE
AS 
    v_readerinfo READERINFO2%ROWTYPE;
    v_elmts varchar2(30);

    CURSOR cursor_readerinfose
    IS 
    SELECT * FROM READERINFO2
    WHERE UNIT = v_elmts
    ORDER BY UNIT; -- 聲明遊標和關聯條件,查詢條件中使用了變量v_elmts

BEGIN 
PRO_OUT_ELT(v_elmts); -- 調用存儲過程PRO_OUT_ELT,爲v_elmts賦值
    
OPEN cursor_readerinfose;
    LOOP
        FETCH cursor_readerinfose INTO v_readerinfo;
        EXIT WHEN cursor_readerinfose%NOTFOUND;
        IF V_readerinfo.bookcount < 3 THEN 
            UPDATE READERINFO2 SET BOOKCOUNT = BOOKCOUNT+1
            WHERE READERID = v_readerinfo.readerid;
            DBMS_OUTPUT.PUT_LINE('數據修改完畢...');
        END IF;
    END LOOP;
END;
/
  1. 建立PRO_OUT_EL, PRO_READER_CLOSE 利用EXEC命令 PRO_READER_CLOSE

TIPScode

調用OUT類型參數得存儲過程時,須要用變量填充,而不能用常量表達式填充。server

在調用存儲過程當中,若是因發生未處理的異常而中斷,那麼調用者通常不會獲得任何OUT參數的值,而在異常被處理的狀況下推出,在發生一次航以前所獲取的OUT參數值將被調用者得到。對象

在存儲過程當中某個參數既能夠是輸入參數也能夠是輸出參數類型的參數,它既能夠接收數據,也能夠返回數據。
parameter IN OUT datatype

查看存儲過程

在Oracle的數據字典 USER_SOURCE 中記錄用戶定義的存儲過程的元數據

  • 從 USER_SOURCE 中查詢當前用戶的全部存儲過程名稱
SELECT DISTINCT NAME FROM USER_SOURCE 
WHERE TYPE = 'PROCEDURE'
-- 只查看當前用戶全部的存儲過程,不查看具體的腳本
SELECT * FORM USER_OBJECTS WHERE object_type = 'PROCEDURE';
  • 查詢存儲過程的建立腳本
SELECT NAME, LINE, TEXT, FROM USER_SOURCE-- line爲腳本編號 text裏面存放了存儲過程的相關腳本
WHERE TYPE = 'PROCEDURE' AND NAME = 'PRO_READER'

查看存儲過程的錯誤

錯誤提示語句的結構
SHOW ERRORS PROCEDURE procedure_name

-- 該腳本有錯誤 編譯錯誤 '計算機系'後面少了分號
CREATE PROCEDURE PRO_READER2
AS 

BEGIN
    UPDATE READERINFO2 SET BOOKCOUNT = BOOKCOUNT+1
    WHERE UNIT = '計算機系'

END;
/

存儲過程的修改

CREATE [OR REPLACE] PROCEDURE [schema.] procedure_name 
[parameter_name] [[IN] datatype [{:=|DEFAULT} expression] 
| {OUT | IN OUT} [NOCOPY] datatype][,...]{IS | AS} BODY;
  • [OR REPLACE] 項是可選部分,當省略時表示全新的建立,不然表示覆蓋原有的存儲過程。一般帶着該選項,這樣方便修改存儲過程。

存儲過程的從新編譯

當存儲過程的引用對象失效時調用者就會出現失效的狀況,當這種狀況出現時,只要不是腳本出現問題,只須要從新編譯就能夠正常使用了。
ALTER PROCEDURE procedure_name COMPILE;

刪除存儲過程

DROP PROCEDURE [ schema. ] procedure_name

函數的建立語法結構

CREATE FUNCTION [ schema. ] function_name
    [
    (paramter_declaration [, paramter_declaration])
    ]
    RETURN datatype
    {IS | AS}
    [declare_selection]
    
    BEGIN 
        statement [ statement | pagma ]...
            [EXCEPTION exception_handler [ exception_handler] ... ]
    END [name];
/

使用自定義函數注意

自定義函數儘可能不要操做數據庫數據

若是在標準SQL調用自定義函數,那麼被調用函數不容許有輸出類型的參數。

若是在標準SQL中調用自定義函數,那麼被調用函數將不能有事務操做語句和DDL語句等。

查詢或增長、修改、刪除操做所調用的函數降不容許操做任何數據表

建立無參數函數

  • 要求建立函數,該函數能夠返回當前的登陸用戶
CREATE FUNCTION MYUSER
RETURN VARCHAR2
IS 
    v_qnty VARCHAR2(20); --表示聲明函數內部的變量,爲VARCHAR2類型

BEGIN
    SELECT SYS.LOGIN_USER INTO v_qnty
    FROM DUAL;
    RETURN v_qnty;
END;
/

建立有參數函數

CREATE FUNCTION GETUNIT(in_readerid IN VARCHAR2) --建立函數GETUNIT,帶有一個輸入類型的參數
RETURN VARCHAR2 IS 
    v_readerid VARCHAR2(20);
BEGIN
    SELECT UNIT INTO v_readerid FROM READERINFO2 WHERE
    READERID = inreaderid;
    RETURN v_readerid;
END;
/
var v_unit VARCHAR2(10);
EXEC :v_unit := GETUNIT('9702')
  • 要求建立函數,該函數帶有兩個輸出參數,在根據BOOKID查詢BOOKINFO表時,可以返回圖書名稱、出版社及做者
CREATE FUNCTION GETBOOKINFO(in_bookid IN NUMBER, out_pulish OUT VARCHAR2, out_author OUT VARCHAR2)
RETURN VARCHAR2
IS 
    v_bookname VARCHAR2(20);
    v_out_publish VARCHAR2(50);
    v_out_author VARCHAR2(50);

BEGIN
    SELECT BOOKNAME. PUBLISH, AUTHOR INTO 
    v_bookname, v_out_publish, v_author
    FROM BOOKID = in_bookid;
    out_publish := v_out_publish;
    out_author := v_out_author;
    RETURN v_bookname;
END;
/
  • 在不增長函數參數的基礎上,返回圖書的價格
CREATE FUNCTION GETBOOKINFO(in_bookid IN OUT NUMBER, out_pulish OUT VARCHAR2, out_author OUT VARCHAR2)
RETURN VARCHAR2
IS 
    v_bookname VARCHAR2(20);
    v_out_publish VARCHAR2(50);
    v_out_author VARCHAR2(50);
    v_out_price NUMBER(8);

BEGIN
    SELECT BOOKNAME. PUBLISH, AUTHOR, PRICE INTO 
    v_bookname, v_out_publish, v_author, v_out_price
    FROM BOOKID = in_bookid;
    out_publish := v_out_publish;
    out_author := v_out_author;
    in_bookid := v_out_price;
    RETURN v_bookname;
END;
/

查看函數

-- 查看函數列表
SELECT OBJECT_NAEM, OBJECT_ID, STATUS FROM USER_OBJECTS WHERE OBJECT_TYPE = 'FUNCTION';/
-- 查看函數相關腳本
SELECT * FROM USER_SOURCE WHERE TYPE = 'FUNCTION' AND NAME = 'MYUSER' ORDER BY LINE;/

修改函數

CREATE OR REPLACE FUNCTION MYUSER
RETURN VARCHAR2
IS 
    v_qnty VARCHAR2(20); --表示聲明函數內部的變量,爲VARCHAR2類型

BEGIN
    SELECT SYS.LOGIN_USER INTO v_qnty
    FROM DUAL;
    RETURN v_qnty;
END;
/

從新、刪除編譯函數

ALTER FUNCTION function_name COMILE;
DROP FUNCTION function_name;

參考資料:

  1. 書籍 ORCACLE PL/SQL寶典

歡迎關注微信公衆號哦~ ~

相關文章
相關標籤/搜索