日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle 存储过程,函数和包。

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

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

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

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


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

執行stored procedure 的用戶必須是其owner 或者具有EXECUTE ANY PROCEDURE 的權限。

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

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

例1:
步驟1: 登錄SCOTT帳號 (默認密碼是tiger)
步驟2: 創建1個返回雇員總人數的stored procedure



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

步驟3:執行存儲過程。


例2:
循環列出,emp表中所有員工name, 并調用上面的存儲過程顯示總人數。
步驟1: 編寫Stored procedure 如下圖


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

步驟2: 執行stored procedure.




?
?
?

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

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

用法如下:

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

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

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

?如果省略INOUT 或 IN OUT關鍵字,則默認是IN.

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


步驟2: 執行sp如下圖

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

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

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







1.3 創建和刪除存儲函數
????? 創建函數,需要CREATE PROCEDURE 或 CREATE ANY PROCEDURE的系統權限。

????? 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];

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

??????? 重新編譯一個存儲函數時,編譯的人應該是函數的創建者或者擁有ALTER ANY PROCEDURE系統權限的人,重新編譯一個存儲函數的語法如下:

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

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

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


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



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

1.5 存儲過程和函數的查看
?????? 可以通過對數據字典的訪問來查詢存儲過程或函數的有關信息,如果要查詢當前用戶的存儲過程或函數的源代碼,可以通過對USER_SOURCE數據字典視圖查詢得到。USER_SOURCE的結構如下:


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


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

?

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

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








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


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

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




2.包 (Package)

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


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


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

???????????
?
????????? 在包體中出現的過程或函數,如果需要對外公用,就必須在包頭中說明,包頭中的說明應該和包體中的說明一致。

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

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

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

?????????? * 區分了共有過程和私有過程,包的私有過程增強了過程和函數的保密性.

??????????? * 包在被首次調用時,就作為1個整體被全部調入內存,減少了多次訪問過程或函數的I/O次數.


2.4 創建包和包體
??????????

??????????? 包由包頭和包體兩部分組成, 包的創建應該先創建包頭部分, 然后再創建包體部分. 創建, 刪除和編譯包的權限同創建,刪除和編譯存儲過程的權限相同.

創建包頭命令如下:

CREATE [OR REPLACE] PACKAGE PK_NAME
IS

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

函數說明
過程說明

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

創建包體命令如下:
CREATE [OR REPLACE] PACKAGE BODY PK_NAME
IS

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

END;?

刪除包頭:
Drop Package PKNAME

刪除包頭:
Drop Package body PKNAME

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

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


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



?
2.6 包的應用

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

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

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

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

包頭部分:


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


SAVE_EMP:
?
CHANGE NAME及 CHANGE_SAL:
?

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


步驟3: 顯示雇員信息:


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

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







?

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。