存储过程与函数oracle
| 存儲在數(shù)據(jù)庫中供所有用戶程序調(diào)用的子程序叫做存儲過程,存儲函數(shù)。 存儲過程是在大型數(shù)據(jù)庫系統(tǒng)中,用PL/SQL語言編寫的能完成一定處理功能的存儲在數(shù)據(jù)庫字典中的程序,它是一個命名的 PL/SQL 塊,經(jīng)編譯后存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名字并給出參數(shù)(如果該存儲過程帶有參數(shù))來執(zhí)行它。 存儲過程是數(shù)據(jù)庫中的一個重要對象,任何一個設(shè)計良好的數(shù)據(jù)庫應(yīng)用程序都應(yīng)該用到存儲過程。 為保證調(diào)用多個存儲過程中處在同一個事務(wù)中,所以一般不在存儲過程或者存儲函數(shù)中,commit或rollback; | |||||||
| 語 法 |
其中參數(shù)IN表示輸入?yún)?shù),是參數(shù)的默認模式。 OUT表示返回值參數(shù),類型可以使用任意Oracle中的合法類型。 OUT模式定義的參數(shù)只能在過程體內(nèi)部賦值,表示該參數(shù)可以將某個值傳遞回調(diào)用他的過程 IN OUT表示該參數(shù)可以向該過程中傳遞值,也可以將某個值傳出去。 存儲過程參數(shù)不帶取值范圍,in表示傳入,out表示輸出; 變量帶取值范圍,后面接分號; 在判斷語句前最好先用count(*)函數(shù)判斷是否存在該條操作記錄; 用select … into … 給變量賦值; 在代碼中拋異常用 raise+異常名; | ||||||
| 調(diào)用存儲過程的兩種方式 |
| ||||||
| 將過程的 執(zhí)行權(quán)限 授予其他 用戶 | SQL> GRANT EXECUTE ON find_emp TO MARTIN; SQL> GRANT EXECUTE ON swap TO PUBLIC; | ||||||
| 和函 數(shù) 區(qū)別 | 一般來講,過程和函數(shù)的區(qū)別在于函數(shù)可以有一個返回值;而過程沒有返回值。但過程和函數(shù)都可以通過 out 指定一個或多個輸出參數(shù)。我們可以利用 out 參數(shù),在過程和函數(shù)中實現(xiàn)返回多個值 1 如果存儲過程想實現(xiàn)有返回值的業(yè)務(wù),我們就必須使用out類型的參數(shù)。 如果只有一個返回值,用存儲函數(shù);否則,就用存儲過程 過程和函數(shù)都可以通過out指定一個或多個輸出參數(shù)。我們可以利用out參數(shù),在過程和函數(shù)中實現(xiàn)返回多個值;?
| ||||||
| 1.在oracle中,數(shù)據(jù)表別名不能加as,如: select a.appname from appinfo a;-- 正確 select a.appname from appinfo as a;-- 錯誤 2.在存儲過程中,select某一字段時,后面必須緊跟into,如果select整個記錄,利用游標的話就另當別論了。 3.在利用select…into…語法時,必須先確保數(shù)據(jù)庫中有該條記錄,否則會報出”no data found”異常。 4.在存儲過程中,別名不能和字段名稱相同,否則雖然編譯可以通過,但在運行階段會報錯 5.select sum(vcount) into fcount from A where bid='xxxxxx'; 如果A表中不存在bid=”xxxxxx”的記錄,則fcount=null(即使fcount定義時設(shè)置了默認值, 如:fcount number(8):=0依然無效,fcount還是會變成null), 這樣以后使用fcount時就可能有問題,所以在這里最好先判斷一下: if fcount is null then ? ? fcount:=0; end if; | |||||||
| 觸發(fā)器 觸發(fā)器是一種特殊的存儲過程,觸發(fā)器在數(shù)據(jù)庫里以獨立的對象存儲,它與存儲過程和函數(shù)不同的是,存儲過程與函數(shù)需要用戶顯示調(diào)用才執(zhí)行,而觸發(fā)器是由一個事件來啟動運行。即觸發(fā)器是當某個事件發(fā)生時自動地隱式運行。并且,觸發(fā)器不能接收參數(shù)。所以運行觸發(fā)器就叫觸發(fā)或點火(firing)。ORACLE事件指的是對數(shù)據(jù)庫的表進行的INSERT、UPDATE及DELETE操作或?qū)σ晥D進行類似的操作。ORACLE將觸發(fā)器的功能擴展到了觸發(fā)ORACLE,如數(shù)據(jù)庫的啟動與關(guān)閉等。所以觸發(fā)器常用來完成由數(shù)據(jù)庫的完整性約束難以完成的復(fù)雜業(yè)務(wù)規(guī)則的約束,或用來監(jiān)視對數(shù)據(jù)庫的各種操作,實現(xiàn)審計的功能。? 1、觸發(fā)器類型 主要有DML觸發(fā)器、替代觸發(fā)器、系統(tǒng)事件觸發(fā)器和DDL觸發(fā)器。 DML觸發(fā)器:ORACLE可以在DML語句進行觸發(fā),可以在DML操作前(BEFORE觸發(fā)器)或操作后(AFTER觸發(fā)器)進行觸發(fā),并且可以對每個行或語句操作上進行觸發(fā)(行級觸發(fā)器和語句級觸發(fā)器)。? INSTEAD OF觸發(fā)器:又稱為替代觸發(fā)器,用于執(zhí)行一個替代操作來代替觸發(fā)事件的操作,?由于在ORACLE里,不能直接對由兩個以上的表建立的視圖進行操作。所以給出了替代觸發(fā)器。 系統(tǒng)事件觸發(fā)器:在發(fā)生如數(shù)據(jù)庫啟動或者關(guān)閉等系統(tǒng)事件時觸發(fā)。 DDL觸發(fā)器:由DDL語句觸發(fā),例如CREATE、ALTER和DROP語句。可分為BEFORE觸發(fā)器和AFTER觸發(fā)器。 2、創(chuàng)建觸發(fā)器 使用CREATE TRIGGER語句,語法如下: CREATE?[ OR?REPLACE ]?TRIGGER?trigger_name { BEFORE?|?AFTER?| INSTEAD?OF } { INSERT?|?DELETE?|?UPDATE?[ OF?column?[,?column?… ] ] } ?#tigger_event [ OR?{ INSERT?|?DELETE?|?UPDATE?[OF?column?[,?column?… ] ] } ... ] ON?[ schema. ] table_name?|?[ schema.] view_name?| [ DATAASE ] [ REFERENCING??{ OLD?[ AS ]?old?|?NEW?[ AS ] ?new |?PARENT?as?parent } ] [ FOR?EACH?ROW?] [ WHEN?trigger_condition ] [ DECLARE declaration_statements ; ] BEGIN trigger_body ; END [ trigger_name ] PL/SQL_BLOCK?|?CALL?procedure_name; 語法說明: trigger_name:觸發(fā)器名稱。 BEFORE?|?AFTER | INSTEAD OF:BEFORE和AFTER表示觸發(fā)器執(zhí)行的時間在觸發(fā)事件的前后,INSTEAD OF表示觸發(fā)器中的事件代替觸發(fā)事件執(zhí)行。 tigger_event:激活觸發(fā)器的事件,例如 INSERT、DELETE、UPDATE?。 ON?[ schema. ] table_name?|?[ schema.] view_name?| [ DATABASE ]:table_name為DML觸發(fā)器所針對的表,如果是替代觸發(fā)器則需要指定視圖名稱(view_name),如果是DDL觸發(fā)器或者系統(tǒng)事件觸發(fā)器,則使用ON DATABASE。 REFERENCING:說明相關(guān)名稱,在行觸發(fā)器的PL/SQL塊和WHEN?子句中可以使用相關(guān)名稱參照當前的新、舊列值,默認的相關(guān)名稱分別為OLD和NEW。觸發(fā)器的PL/SQL塊中應(yīng)用相關(guān)名稱時,必須在它們之前加冒號(:),但在WHEN子句中則不能加冒號。 FOR?EACH?ROW:表示是行級觸發(fā)器,如果未指定則為語句級觸發(fā)器。 WHEN?trigger_condition:為觸發(fā)的運行指定限制條件。 trigger_body:觸發(fā)器體,包含觸發(fā)器的內(nèi)容。 3、DML觸發(fā)器 DML觸發(fā)器由DML語句觸發(fā),對應(yīng)的tigger_event為: { INSERT | DELEATE | UPDATE [ OF column [ , ... ] ] } 說明: DML操作主要包括INSERT、DELETE和UPDATE操作,通過根據(jù)針對的事件,可分為INSERT觸發(fā)器、DELETE觸發(fā)器和UPDATE觸發(fā)器。 可以將DML操作細化到列,即針對某列進行DML操作時激活觸發(fā)器。 任何DML都可按照觸發(fā)時間分為BEFORE和AFTER。 在行級觸發(fā)器中,為了獲得某列在操作前后的數(shù)據(jù),提供兩種特殊標識符:OLD和:NEW,通過:OLD.column_name的形式可以獲取該列的舊數(shù)據(jù),而通過:NEW.colum_name可以獲取該列的新數(shù)據(jù),INSERT觸發(fā)器只能用:NEW,DELETE觸發(fā)器只能用:OLD,UPDATE觸發(fā)器可以用:OLD和:NEW。 注意:如果創(chuàng)建時,不指定FOR EACH ROW,則為與語句級觸發(fā)器,所有受影響的數(shù)據(jù)只處罰一次,因此無法使用:NEW和:OLD獲取某列的新舊數(shù)據(jù)。 4、INSTEAD OF觸發(fā)器 執(zhí)行一個替代操作來代替觸發(fā)事件的操作,而觸發(fā)事件本身不會被執(zhí)行。不過oracle中的INSTEAD OF觸發(fā)器不能針對表,只能針對視圖。 5、系統(tǒng)事件觸發(fā)器 系統(tǒng)事件觸發(fā)器是指由數(shù)據(jù)庫系統(tǒng)事件觸發(fā)的觸發(fā)器,支持的系統(tǒng)事件如下: 系統(tǒng)事件 說明 LOGOFF 用戶從數(shù)據(jù)庫注銷 LOGON 用戶登錄數(shù)據(jù)庫 SERVERERROR 服務(wù)器發(fā)生錯誤 SHUTDOWN 關(guān)閉數(shù)據(jù)庫實例 STARTUP 打開數(shù)據(jù)庫實例 注:對于LOGOFF和SHUTDOWN事件只能創(chuàng)建BEFORE觸發(fā)器,對于LOGON、SERVERERROR和STARTUP事件只能創(chuàng)建AFTER觸發(fā)器。 創(chuàng)建系統(tǒng)觸發(fā)器需要使用ON DATABASE子句,表示創(chuàng)建的觸發(fā)器是數(shù)據(jù)庫級觸發(fā)器。創(chuàng)建系統(tǒng)事件觸發(fā)器需要用戶具有DBA權(quán)限。 6、DDL觸發(fā)器 DDL觸發(fā)器由DDL語句觸發(fā),可分為:BEFORE觸發(fā)器和AFTER觸發(fā)器,針對事件包含CREATE、ALTER、DROP、ANALYZE、GRANT、COMMENT、REVOKE、RENAME、TRUNCATE、AUDIT、NOTAUDIT、ASSOCIATE STATISTICS和DISASSOCIATE STATISTICS。 創(chuàng)建DDL觸發(fā)器需要用戶具有DBA權(quán)限。 7、禁用與啟用觸發(fā)器 創(chuàng)建時使用ENABLE與DISABLE關(guān)鍵字制定觸發(fā)器初始裝填為啟用或禁用,默認為ENABLE。需要時也可使用ALTER TRIGGER語句修改觸發(fā)器的狀態(tài),如下: ALTER TRIGGER trigger_name ENABLE | DISABLE ; 如果修改某個表上所有觸發(fā)器的狀態(tài),可用如下形式: ALTER TABLE table_name ENABLE | DISABLE ALL TRIGGERS ; 8、修改與刪除觸發(fā)器 修改刪除觸發(fā)器只需要在 CREATE TRIGGER語句中添加OR REPLACE關(guān)鍵字。 刪除觸發(fā)器需要使用DROP TRIGGER語句,具體如下: DROP TRIGGER trigger_name; 包 1、創(chuàng)建包 程序包是對相關(guān)過程、函數(shù)、變量、游標和異常等對象的封裝,程序包由規(guī)范和主體兩部分組成,程序包規(guī)范:聲明類型、變量、常量、異常、游標和子程序等元素條目(不包含這些元素的實際代碼);程序包主體:用于實現(xiàn)在程序包規(guī)范中定義的游標、子程序(包含了元素的實際代碼)。包規(guī)范中的條目為共有項目,可供所有的數(shù)據(jù)庫用戶訪問;而包體中創(chuàng)建的規(guī)范中沒有提到的項目,屬于私有項目,只能在包體中使用。 1)、創(chuàng)建包規(guī)范 創(chuàng)建包規(guī)范使用CREATE PACKAGE語句,如下: CREATE [ OR REPLACE ] PACKAGE package_name { IS | AS } package_specification ; END package_name; 說明: package_name:創(chuàng)建的包名 package_specification:用于列出用戶可以使用的公共存儲過程、函數(shù)、類型和對象。 2)、創(chuàng)建包體 創(chuàng)建包體需要使用CREATE PACKAGE BODY語句,并且在創(chuàng)建的時候需要指定已創(chuàng)建的包,如下: CREATE [ OR REPLACE ] PACKAGE BOODY package_name { IS | AS } package_body ; END package_name ; 2、調(diào)用包 調(diào)用程序包中的元素時,采用如下形式: package_name.[ element_name ] ; element_name:表示元素名稱,可以使存儲過程名、函數(shù)名、變量名和常量名等。 注:程序包中可以定義公有常量和變量,使用的DBMS_OUTPUT.PUT_LINE輸出結(jié)果語句,DBMS_OUTPUT是系統(tǒng)定義的包,PUT_LINE是該包的存儲過程。 3、刪除包 使用DEOP PACKAGE語句,如果程序包被刪除,則包體也被自動刪除。如下: DROP PACKAGE package_name ; ? | |||||||
| ? | |||||||
| ? | |||||||
| ? | |||||||
?
總結(jié)
以上是生活随笔為你收集整理的存储过程与函数oracle的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL为什么要set names
- 下一篇: 面试题2021-2-24