日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Oracle 存储过程,函数和包。

發(fā)布時間:2025/3/20 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle 存储过程,函数和包。 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1. 存儲過程和函數(shù)
1.1 創(chuàng)建和刪除存儲過程
??????????? 創(chuàng)建存儲過程,需要有CREATE PROCEDURE 或 CREATE ANY PROCEDURE的系統(tǒng)權(quán)限.
基本語法如下:

??????????? CREATE? OR REPLACE PROCEDURE? SP_NAME( PM_NAME [IN/OUT/IN OUT] PM_TYPE...)
??????????? {AS}???
??????????? [說明(變量定義)部分]
??????????? BEGIN
????????????????? 可執(zhí)行部分
??????????? [EXCEPTION]
????????????????? 錯誤處理部分
??????????? END [SP_NAME];

參數(shù)部分用于定義若干個參數(shù)(若沒有參數(shù),可以忽略)。參數(shù)有三種形式: IN / OUT 和 IN OUT, 默認為IN。
關(guān)鍵字AS 也可以寫成 IS.

刪除stored procedure 的用戶必須是其owner或者具有 DROP ANY PROCEDURE的權(quán)限。
語法如下:
??????????? DROP PROCEDURE SP_NAME;


如果要重新compile 1個 stored procedure. 則用戶必須是其owner或者擁有 ALTER ANY PROCEDURE的權(quán)限
語法如下:
????????? ALTER PORCEDURE SP_NAME COMPILE;

執(zhí)行stored procedure 的用戶必須是其owner 或者具有EXECUTE ANY PROCEDURE 的權(quán)限。

方法1:
??????? EXECUTE 模式名.SP_NAME[(PARAMETER..];
方法2:
??????? BEGIN
???????????? 模式名.SP_NAME[(PARAMETER..]
??????? END;

如果是調(diào)用本帳戶下的存儲過程, 則模式名可以省略。 要調(diào)用其他帳戶編寫的存儲過程,則模式明必須添加。

例1:
步驟1: 登錄SCOTT帳號 (默認密碼是tiger)
步驟2: 創(chuàng)建1個返回雇員總?cè)藬?shù)的stored procedure



注1: 每一條語句都必須用;結(jié)尾,否則編譯出錯。
注2: 變量名不能用@字符開頭,否則編譯出錯~
注3: 變量從select 語句復(fù)制賦值應(yīng)該 用 select field1, field2 into v_va1,v_val2 from tb_name.
????????? 而不能使用Sybase的? select v_val1 = field1, v_val2 = field2 from tb_name.

步驟3:執(zhí)行存儲過程。


例2:
循環(huán)列出,emp表中所有員工name, 并調(diào)用上面的存儲過程顯示總?cè)藬?shù)。
步驟1: 編寫Stored procedure 如下圖


注1: cursor 也必須定義在as 與 begin end之間。
注2 : 執(zhí)行另1個stored procedure, 直接輸入sp名字加";" 符號就可以。

步驟2: 執(zhí)行stored procedure.




?
?
?

1.2 參數(shù)傳遞
Oracle stored procedure的參數(shù)有3種類型如下:

參數(shù)類型?????????? 說明
IN?????????????????????? 定義1個輸入?yún)?shù)變量,用于傳遞參數(shù)給stored procedure
OUT??????????????????? 定義1個輸出參數(shù)變量,用于從stored procedure中獲取數(shù)據(jù)
IN OUT?????????????? 定義1個輸入輸出參數(shù),同上擁有以上兩個功能。

用法如下:

????? PM_name IN DATA_type DEFAULT default_value;
?????? 定義1個輸入?yún)?shù)變量,用于傳遞參數(shù)給stored procedure.在調(diào)用sp時,主程序的實際參數(shù)可以是常量,有值變量或表達式等。Default關(guān)鍵字為可選項,用來設(shè)定參數(shù)的默認值。如果在調(diào)用stored procedure時不指明參數(shù),則該參數(shù)變量取默認值。 在存儲過程中,輸入變量用于接受主程序傳遞的值,但不能對其進行賦值

????? PM_name OUT DATA_type;
?????? 定義1個輸出參數(shù)變量,用于從stored procedure中獲取數(shù)據(jù),即變量從存儲過程中返回值給程序。
?????? 在調(diào)用sp時,主程序傳給sp的輸出參數(shù)只能是1個變量,不能是常量或者表達式。 在sp中,參數(shù)變量只能被賦值,而不能將其的值賦予其他對象,在sp中必須給輸出變量賦值1次

??????? PM_name IN OUT DATA_type DEFAULT default_value;
??????? 定義1個輸入輸出變量,同時具有以上功能。在調(diào)用sp時,主程序傳給sp的實際參數(shù)只能是變量,而不能是常量或表達式。Default關(guān)鍵字同樣是可選項,用來設(shè)定參數(shù)的默認值。 在sp內(nèi),變量接受主程序傳遞的值,同時可以參加賦值運算,也可以對其賦值。在sp內(nèi)至少對其賦值 一次

?如果省略INOUT 或 IN OUT關(guān)鍵字,則默認是IN.

例3:
編寫1個給員工增加工資的stored procedure CHANGE_SALARY? 通過對IN類型的參數(shù)傳遞 要增加工資的雇員編號和增加的工資額。
步驟1: 編寫sp如下圖:
?


步驟2: 執(zhí)行sp如下圖

可以見到7788的工資由3000 變成3020

參數(shù)傳遞的個數(shù)和順序應(yīng)該與定義的一致,如果順序不一致也可以采用如下方法:
EXECUTE USP_CHANGE_SALARY(p_raise=>20, p_empno=>7788);
?
例4:
使用OUT類型參數(shù)返回stored procedure的結(jié)果。
步驟1: 分別編寫兩個sp, 其中USP_GET_EMP_COUNT通過使用OUT類型參數(shù),將值傳給另1個sp USP_SHOW_EMP_COUNT.
??
步驟2:執(zhí)行sp
?
說明: 在存儲過程中定義了OUT類型的參數(shù)P_TOTAL, 在主程序調(diào)用該存儲過程時,傳遞了參數(shù)v_empcount. 在存儲過程的
select .. into ...語句中對p_total進行賦值。賦值結(jié)果有v_empcount變量帶回給主程序顯示。

例5:
使用IN OUT類型的參數(shù),給電話號碼增加區(qū)碼。
步驟1:
編寫并編譯如下存儲過程:
?
步驟2:
輸入以下命令執(zhí)行該存儲過程:
?
可以見到下面輸出了加了區(qū)號的電話號碼。
注1: Oracle 語句不區(qū)分大小寫
注2 :賦值語句請用:=??? 而不能用=.







1.3 創(chuàng)建和刪除存儲函數(shù)
????? 創(chuàng)建函數(shù),需要CREATE PROCEDURE 或 CREATE ANY PROCEDURE的系統(tǒng)權(quán)限。

????? CREATE [OR REPLACE] FUNCTION func_name[(para_name para_type...)]
????? RETURN Data_type
????? IS
???? ? ? ?? [declare part]
????? Begin
??????????? main part
??????????? RETURN (expression)
????? [EXCEPTION
????????????? errors handle part]
????? END [func_name];

?????? 其中,參數(shù)是可選的,但是只能是IN類型(IN關(guān)鍵字一般被忽略)。
?????? 在定義部分的RETURN 數(shù)據(jù)類型,用來表示函數(shù)的數(shù)據(jù)類型,也就是返回值的數(shù)據(jù)類型,不可忽略。
?????? 在可執(zhí)行部分的Return(表達式),用來生成函數(shù)的返回值,其表達式的類型必須跟定義部分說明的
函數(shù)類型一致。在函數(shù)的執(zhí)行部分可以有多個Return語句,但只有1個會被執(zhí)行,一旦執(zhí)行了return語句,
則函數(shù)結(jié)束并返回調(diào)用環(huán)境。
?????? 一個存儲函數(shù)在不需要時可以換刪除,但刪除的人應(yīng)該是函數(shù)的創(chuàng)建者或者是擁有DROP ANY PROCEDURE系統(tǒng)權(quán)限的人,其語法如下:
? ? ??
? ? ?? DROP FUNCTION func_name;

??????? 重新編譯一個存儲函數(shù)時,編譯的人應(yīng)該是函數(shù)的創(chuàng)建者或者擁有ALTER ANY PROCEDURE系統(tǒng)權(quán)限的人,重新編譯一個存儲函數(shù)的語法如下:

??????? ALTER PROCEDURE func_name COMPILE;

???????? 函數(shù)的調(diào)用者應(yīng)該是函數(shù)的創(chuàng)建者或者擁有EXECUTE ANY PROCEDURE系統(tǒng)權(quán)限的人,或者是被函數(shù)的擁有者授予了函數(shù)執(zhí)行權(quán)限的用戶,函數(shù)的引用和存儲過程不同,函數(shù)需要出現(xiàn)在程序體重,可以參加表達式的運算和單獨出現(xiàn)在表達式中,其形式如下:
?????
???????? Varible_name := func_name(para...);

例6:
??????? 創(chuàng)建1個通過雇員編號返回雇員名稱的函數(shù)GET_EMP_NAME.
??????? 步驟1:
????????????????? 編寫并編譯如下存儲過程


?????? 步驟2: 測試:



會見到如果輸入的數(shù)據(jù)在數(shù)據(jù)庫不存在, 函數(shù)會捕捉錯誤信息。

1.5 存儲過程和函數(shù)的查看
?????? 可以通過對數(shù)據(jù)字典的訪問來查詢存儲過程或函數(shù)的有關(guān)信息,如果要查詢當(dāng)前用戶的存儲過程或函數(shù)的源代碼,可以通過對USER_SOURCE數(shù)據(jù)字典視圖查詢得到。USER_SOURCE的結(jié)構(gòu)如下:


說明: 里面按行存放著過程或函數(shù)的腳步,name 是名字, Type表示類型(SP or function),line是行號,Text為對應(yīng)行的腳本。


?例7: 查詢過程USP_EMPCOUNT的代碼。
?
例8: 查詢函數(shù)GET_EMP_NAME的參數(shù)

?

例9: 查詢USP_EMP_LIST 存儲過程是否可用

?
說明: 這里要從視圖user_objects里查詢,VALID表示該存儲過程有效(即是通過了編譯),INVALID表示無效或未通過編譯。當(dāng)Oracle調(diào)用1個無效的存儲過程或函數(shù)時,首先試圖對其進行編譯,如果編譯成功則將狀態(tài)status設(shè)置成valid并執(zhí)行,否則給出錯誤信息。








????? 當(dāng)1個存儲過程編譯成功,狀態(tài)變成valid,會不會在某些情況下變成invalid呢,結(jié)論是完成可能的,比如1個存儲過程里面喲你道的1張表被update或刪除了。存儲過過程就會變成無效invalid,所以要注意存儲過程和函數(shù)與其他對象的依賴關(guān)系。
????? 如果要檢查stored procs和function的依賴性,可以通過查詢數(shù)據(jù)字典USER_DEPENDENCIES來確定,
? ? ? 該視圖結(jié)構(gòu)如下: ???
???????


說明:
????????? Name為對象名,
????????? Type為對象類型,
????????? referenced_owner 為涉及到的(被依賴的)對象的擁有者賬戶,
????????? referenced_name?? 被依賴的對象名
????????? referenced_type??? 被依賴的對象的類型
?????????
參考下圖:
?

?????????? 還有一種情況需要注意,如果1個用戶A被授予執(zhí)行屬于用戶B的一個存儲過程,在用戶B的存儲過后層訪問到用戶C的表,用戶B被授予訪問用戶C表的權(quán)限,但用戶A沒有授予訪問用戶C的表的權(quán)限,那么用戶A調(diào)用用戶B的存儲過程是失敗的還是成功的呢?答案是成功的,可以自己實際測試下。




2.包 (Package)

2.1 包的概念和組成
?????????
包是用來存儲相關(guān)程序結(jié)構(gòu)的對象,他存儲與數(shù)據(jù)字典中,包由兩個分離的部分組成,包頭(Package)和包體(Package body).包頭是包的說明部分, 是對外的操作接口,對應(yīng)用是可見的,包體是包的代碼的實驗部分,對應(yīng)用來說是不可見的黑盒。


2.2 包中包含的程序結(jié)構(gòu)
???????????? 包中可以包含的程序結(jié)構(gòu)如下面這張表所示。
???????????????????????????????????? 包中包含的程序結(jié)構(gòu)
????????????? 程序結(jié)構(gòu)?????????????????????????????? 說明
????????????? 過程(Procedure)??????????????????? 帶參數(shù)的命名的程序模塊
????????????? 函數(shù)(Function)????????????????????? 帶參數(shù),具有返回值的命名程序模塊
????????????? 變量(Variable)?????????????????????? 存儲變化的量的存儲單元
????????????? 常量(Constant)????????????????????? 存儲不變的量的存儲單元
????????????? 游標(Cursor)????????????????????????? 用戶定義的數(shù)據(jù)操作緩存去,可以在執(zhí)行部分使用。
????????????? 類型(Type)??????????????????????????? 用戶定義的新的結(jié)構(gòu)類型
????????????? 異常(Exception)???????????????????? 在標準包中定義或由用戶自定義,用戶處理程序錯誤。


?
??????????????
???????????????????????????????????????????????
???????????????
2.3 包中元素的性質(zhì)
???
說明部分可以出現(xiàn)在包的三個不同部分,出現(xiàn)在包頭中的稱為共有元素,出現(xiàn)在包體中的稱為私有元素,出現(xiàn)在包體的過程或函數(shù)中的稱為局部變量。 他們的性質(zhì)有所不同,如下表中表示

???????????
?
????????? 在包體中出現(xiàn)的過程或函數(shù),如果需要對外公用,就必須在包頭中說明,包頭中的說明應(yīng)該和包體中的說明一致。

????????? 包有以下優(yōu)點:
????????? * 包可以方便地將存儲過程和函數(shù)組織到一起,每個包又是相互獨立的. 在不同的包中,過程,函數(shù)都可以重名,這解決了同1個用戶環(huán)境中命名的沖突問題

?????????? *包增強了對存儲過程和函數(shù)的安全管理,對整個包的訪問權(quán)只需要一次授予.

?????????? *在同1個會話中,公用變量的值將被保留,知道會話結(jié)束.

?????????? * 區(qū)分了共有過程和私有過程,包的私有過程增強了過程和函數(shù)的保密性.

??????????? * 包在被首次調(diào)用時,就作為1個整體被全部調(diào)入內(nèi)存,減少了多次訪問過程或函數(shù)的I/O次數(shù).


2.4 創(chuàng)建包和包體
??????????

??????????? 包由包頭和包體兩部分組成, 包的創(chuàng)建應(yīng)該先創(chuàng)建包頭部分, 然后再創(chuàng)建包體部分. 創(chuàng)建, 刪除和編譯包的權(quán)限同創(chuàng)建,刪除和編譯存儲過程的權(quán)限相同.

創(chuàng)建包頭命令如下:

CREATE [OR REPLACE] PACKAGE PK_NAME
IS

共有變量定義
共有類型定義
共有游標定義
共有異常定義

函數(shù)說明
過程說明

END;?????????????????????

創(chuàng)建包體命令如下:
CREATE [OR REPLACE] PACKAGE BODY PK_NAME
IS

私有變量定義
私有類型定義
私有游標定義
私有異常定義
函數(shù)定義
過程定義

END;?

刪除包頭:
Drop Package PKNAME

刪除包頭:
Drop Package body PKNAME

重新編譯包頭:
Alter Package PKNAME COMPILE PACKAGE
?
重新編譯包體:
Alter Package PKNAME COMPILE PACKAGE BODY

在包頭說明的對象可以在包外調(diào)用,調(diào)用的方法和調(diào)用單獨的過程或函數(shù)方法基本相同, 唯一的區(qū)別就是要在調(diào)用的過程或函數(shù)名子前加上包的名字(中間要用".")分隔.? 但要注意.不同的session將單獨對包的公用變量進行初始化,所以不同的session會對包的調(diào)用屬于不同的應(yīng)用.


2.5 系統(tǒng)包
?????? Oracle預(yù)定義了很多標準的系統(tǒng)包, 這些包可以在應(yīng)用中直接使用,比如在例子中我們使用的DBMS_OUTPUT包,就是其中1個系統(tǒng)包,而PUT_LINE是該包的一個函數(shù). 常用的系統(tǒng)包如下面表所示:



?
2.6 包的應(yīng)用

????? 在sql*plus環(huán)境下,包和包體可以分別編譯,也可以一齊編譯. 如果分別編譯,則要先編譯包頭,再編譯包體,如果一齊編譯,則包頭寫在前,包體在后,中間用"/"分隔.

????? 可以將已經(jīng)存在的SP或function添加到包中,犯法是去掉過程或函數(shù)的創(chuàng)建語句CREATE OR REPLACE部分, 將存儲過程或函數(shù)復(fù)制到包體中,然后重新編譯即可.

?????? 如果需要將私有過程或函數(shù)變成共有過程或函數(shù)的話, 將過程或函數(shù)說明部分復(fù)制到到包頭說明部分,然后重新編譯就可以了.
???????
???????
例10: 創(chuàng)建管理雇員信息的包PAK_EMP, 它具有從EMP表獲得雇員信息,修改雇員名稱,修改雇員工資和寫回EMP表的功能.

步驟1:
編寫如下代碼并編譯.

包頭部分:


包體部分:
聲明部分及 SHOW_DETAIL:
?
?
GET_EMP:


SAVE_EMP:
?
CHANGE NAME及 CHANGE_SAL:
?

步驟2:獲取雇員7788的信息:
?


步驟3: 顯示雇員信息:


步驟4: 修改雇員工資:
?注意此時 修改是變量emp_row 也就是員工7788的工資.而且未寫入數(shù)據(jù)庫.

步驟5: 將雇員信息寫入emp表:
?
說明: row_emp作為包PAK_EMP的私有變量,只能被包里面的對象所訪問.







?

總結(jié)

以上是生活随笔為你收集整理的Oracle 存储过程,函数和包。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。