存儲過程與函數oracle

存儲在數據庫中供所有用戶程序調用的子程序叫做存儲過程存儲函數。

存儲過程是在大型數據庫系統中,用PL/SQL語言編寫的能完成一定處理功能的存儲在數據庫字典中的程序,它是一個命名的 PL/SQL 塊,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。

存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。
存儲過程的各個部分:
聲明部分
可執行部分
異常處理部分(可選)
存儲過程的分類:
帶參存儲過程
不帶參存儲過程

爲保證調用多個存儲過程中處在同一個事務中,所以一般不在存儲過程或者存儲函數中,commit或rollback;

無參存儲過程語法 帶參存儲過程 帶參數存儲過程含賦值方式

create or replace procedure NoParPro 

as  //聲明 

begin // 執行 

exception//存儲過程異常 

end;

create or replace procedure queryempname(sfindno emp.empno%type)  

as 

   sName emp.ename%type; 

   sjob emp.job%type; 

begin 

       .... 

exception 

       .... 

end;

create or replace procedure runbyparmeters   

    (isal in emp.sal%type,  

     sname out varchar

     sjob in out varchar

 as  

    icount number; 

 begin 

      select count(*) into icount from emp where sal>isal and job=sjob; 

      if icount=1 then 

        .... 

      else 

       .... 

     end if; 

exception 

     when too_many_rows then 

     DBMS_OUTPUT.PUT_LINE('返回值多於1行'); 

     when others then 

     DBMS_OUTPUT.PUT_LINE('在RUNBYPARMETERS過程中出錯!'); 

end;

其中參數IN表示輸入參數,是參數的默認模式。

OUT表示返回值參數,類型可以使用任意Oracle中的合法類型。

OUT模式定義的參數只能在過程體內部賦值,表示該參數可以將某個值傳遞迴調用他的過程

IN OUT表示該參數可以向該過程中傳遞值,也可以將某個值傳出去。

存儲過程參數不帶取值範圍,in表示傳入,out表示輸出; 變量帶取值範圍,後面接分號;

在判斷語句前最好先用count(*)函數判斷是否存在該條操作記錄; 用select … into … 給變量賦值; 在代碼中拋異常用 raise+異常名;

調用存儲過程的兩種方式

1、SQL>exec proc_emp(‘參數1’,’參數2’);//無返回值過程調用

2、SQL>var vsal number

SQL> exec proc_emp (‘參數1’,:vsal);// 有返回值過程調用

或者:call proc_emp (‘參數1’,:vsal);// 有返回值過程調用

begin

            sayHelloWorld();

            sayHelloWorld();

      end;

將過程的

執行權限

授予其他

用戶

SQL> GRANT EXECUTE ON find_emp TO MARTIN;

SQL> GRANT EXECUTE ON swap TO PUBLIC;

和函

區別

一般來講,過程和函數的區別在於函數可以有一個返回值;而過程沒有返回值。但過程和函數都可以通過 out 指定一個或多個輸出參數。我們可以利用 out 參數,在過程和函數中實現返回多個值

1 如果存儲過程想實現有返回值的業務,我們就必須使用out類型的參數。
2 即便是存儲過程使用了out類型的參數,起本質也不是真的有了返回值,
3 而是在存儲過程內部給out類型參數賦值,在執行完畢後,我們直接拿到輸出類型參數的值。

如果只有一個返回值,用存儲函數;否則,就用存儲過程

過程和函數都可以通過out指定一個或多個輸出參數。我們可以利用out參數,在過程和函數中實現返回多個值; 

  • 存儲過程和存儲函數都可以有out參數;
  • 存儲過程和存儲函數都可以有多個out參數;
  • 存儲過程可以通過out參數來實現返回值。
  • 相同點:1).創建語法結構相似,都可以攜帶多個傳入參數和傳出參數。
    2).都是一次編譯,多次執行。
    不同點:1).存儲過程定義關鍵字用procedure,函數定義用function。
    2).存儲過程中不能用return返回值,但函數中可以,而且函數中必須有return子句。procedur不叫返回值,叫帶出,可以帶出多個值;
    3).執行方式略有不同,存儲過程的執行方式有兩種(1.使用execute2.使用begin和end),函數除了存儲過程的兩種方式外,還可以當做表達式使用,例如放在select中(select f1() form dual;)。
    4).在sql數據操縱語句中只能調用函數而不能調用存儲過程,
  • 模塊化
    將程序分解爲邏輯模塊
    可重用性
    可以被任意數目的程序調用
    可維護性
    簡化維護操作
    安全性
    通過設置權限,使數據更安全
    提高性能
  • 函數不能獨立運行,過程可作爲一個獨立的PL/SQL語句運行
1.在oracle中,數據表別名不能加as,如:
select a.appname from appinfo a;-- 正確
select a.appname from appinfo as a;-- 錯誤
2.在存儲過程中,select某一字段時,後面必須緊跟into,如果select整個記錄,利用遊標的話就另當別論了。
3.在利用select…into…語法時,必須先確保數據庫中有該條記錄,否則會報出”no data found”異常。
4.在存儲過程中,別名不能和字段名稱相同,否則雖然編譯可以通過,但在運行階段會報錯
5.select sum(vcount) into fcount from A where bid='xxxxxx';
如果A表中不存在bid=”xxxxxx”的記錄,則fcount=null(即使fcount定義時設置了默認值,
如:fcount number(8):=0依然無效,fcount還是會變成null),
這樣以後使用fcount時就可能有問題,所以在這裏最好先判斷一下:
if fcount is null then
    fcount:=0;
end if;
觸發器
觸發器是一種特殊的存儲過程,觸發器在數據庫裏以獨立的對象存儲,它與存儲過程和函數不同的是,存儲過程與函數需要用戶顯示調用才執行,而觸發器是由一個事件來啓動運行。即觸發器是當某個事件發生時自動地隱式運行。並且,觸發器不能接收參數。所以運行觸發器就叫觸發或點火(firing)。ORACLE事件指的是對數據庫的表進行的INSERT、UPDATE及DELETE操作或對視圖進行類似的操作。ORACLE將觸發器的功能擴展到了觸發ORACLE,如數據庫的啓動與關閉等。所以觸發器常用來完成由數據庫的完整性約束難以完成的複雜業務規則的約束,或用來監視對數據庫的各種操作,實現審計的功能。 
1、觸發器類型
主要有DML觸發器、替代觸發器、系統事件觸發器和DDL觸發器。
DML觸發器:ORACLE可以在DML語句進行觸發,可以在DML操作前(BEFORE觸發器)或操作後(AFTER觸發器)進行觸發,並且可以對每個行或語句操作上進行觸發(行級觸發器和語句級觸發器)。 
INSTEAD OF觸發器:又稱爲替代觸發器,用於執行一個替代操作來代替觸發事件的操作, 由於在ORACLE裏,不能直接對由兩個以上的表建立的視圖進行操作。所以給出了替代觸發器。
系統事件觸發器:在發生如數據庫啓動或者關閉等系統事件時觸發。
DDL觸發器:由DDL語句觸發,例如CREATE、ALTER和DROP語句。可分爲BEFORE觸發器和AFTER觸發器。
2、創建觸發器
使用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:觸發器名稱。
BEFORE | AFTER | INSTEAD OF:BEFORE和AFTER表示觸發器執行的時間在觸發事件的前後,INSTEAD OF表示觸發器中的事件代替觸發事件執行。
tigger_event:激活觸發器的事件,例如 INSERT、DELETE、UPDATE 。
ON [ schema. ] table_name | [ schema.] view_name | [ DATABASE ]:table_name爲DML觸發器所針對的表,如果是替代觸發器則需要指定視圖名稱(view_name),如果是DDL觸發器或者系統事件觸發器,則使用ON DATABASE。
REFERENCING:說明相關名稱,在行觸發器的PL/SQL塊和WHEN 子句中可以使用相關名稱參照當前的新、舊列值,默認的相關名稱分別爲OLD和NEW。觸發器的PL/SQL塊中應用相關名稱時,必須在它們之前加冒號(:),但在WHEN子句中則不能加冒號。
FOR EACH ROW:表示是行級觸發器,如果未指定則爲語句級觸發器。
WHEN trigger_condition:爲觸發的運行指定限制條件。
trigger_body:觸發器體,包含觸發器的內容。
3、DML觸發器
DML觸發器由DML語句觸發,對應的tigger_event爲:
{ INSERT | DELEATE | UPDATE [ OF column [ , ... ] ] }
說明:
DML操作主要包括INSERT、DELETE和UPDATE操作,通過根據針對的事件,可分爲INSERT觸發器、DELETE觸發器和UPDATE觸發器。
可以將DML操作細化到列,即針對某列進行DML操作時激活觸發器。
任何DML都可按照觸發時間分爲BEFORE和AFTER。
在行級觸發器中,爲了獲得某列在操作前後的數據,提供兩種特殊標識符:OLD和:NEW,通過:OLD.column_name的形式可以獲取該列的舊數據,而通過:NEW.colum_name可以獲取該列的新數據,INSERT觸發器只能用:NEW,DELETE觸發器只能用:OLD,UPDATE觸發器可以用:OLD和:NEW。
注意:如果創建時,不指定FOR EACH ROW,則爲與語句級觸發器,所有受影響的數據只處罰一次,因此無法使用:NEW和:OLD獲取某列的新舊數據。
4、INSTEAD OF觸發器
執行一個替代操作來代替觸發事件的操作,而觸發事件本身不會被執行。不過oracle中的INSTEAD OF觸發器不能針對表,只能針對視圖。
5、系統事件觸發器
系統事件觸發器是指由數據庫系統事件觸發的觸發器,支持的系統事件如下:
系統事件
說明
LOGOFF
用戶從數據庫註銷
LOGON
用戶登錄數據庫
SERVERERROR
服務器發生錯誤
SHUTDOWN
關閉數據庫實例
STARTUP
打開數據庫實例
注:對於LOGOFF和SHUTDOWN事件只能創建BEFORE觸發器,對於LOGON、SERVERERROR和STARTUP事件只能創建AFTER觸發器。
創建系統觸發器需要使用ON DATABASE子句,表示創建的觸發器是數據庫級觸發器。創建系統事件觸發器需要用戶具有DBA權限。
6、DDL觸發器
DDL觸發器由DDL語句觸發,可分爲:BEFORE觸發器和AFTER觸發器,針對事件包含CREATE、ALTER、DROP、ANALYZE、GRANT、COMMENT、REVOKE、RENAME、TRUNCATE、AUDIT、NOTAUDIT、ASSOCIATE STATISTICS和DISASSOCIATE STATISTICS。
創建DDL觸發器需要用戶具有DBA權限。
7、禁用與啓用觸發器
創建時使用ENABLE與DISABLE關鍵字制定觸發器初始裝填爲啓用或禁用,默認爲ENABLE。需要時也可使用ALTER TRIGGER語句修改觸發器的狀態,如下:
ALTER TRIGGER trigger_name ENABLE | DISABLE ;
如果修改某個表上所有觸發器的狀態,可用如下形式:
ALTER TABLE table_name ENABLE | DISABLE ALL TRIGGERS ;
8、修改與刪除觸發器
修改刪除觸發器只需要在 CREATE TRIGGER語句中添加OR REPLACE關鍵字。
刪除觸發器需要使用DROP TRIGGER語句,具體如下:
DROP TRIGGER trigger_name;

1、創建包
程序包是對相關過程、函數、變量、遊標和異常等對象的封裝,程序包由規範和主體兩部分組成,程序包規範:聲明類型、變量、常量、異常、遊標和子程序等元素條目(不包含這些元素的實際代碼);程序包主體:用於實現在程序包規範中定義的遊標、子程序(包含了元素的實際代碼)。包規範中的條目爲共有項目,可供所有的數據庫用戶訪問;而包體中創建的規範中沒有提到的項目,屬於私有項目,只能在包體中使用。
1)、創建包規範
創建包規範使用CREATE PACKAGE語句,如下:
CREATE [ OR REPLACE ] PACKAGE package_name
{ IS | AS }
package_specification ;
END package_name;
說明:
package_name:創建的包名
package_specification:用於列出用戶可以使用的公共存儲過程、函數、類型和對象。
2)、創建包體
創建包體需要使用CREATE PACKAGE BODY語句,並且在創建的時候需要指定已創建的包,如下:
CREATE [ OR REPLACE ] PACKAGE BOODY package_name
{ IS | AS }
package_body ;
END package_name ;
2、調用包
調用程序包中的元素時,採用如下形式:
package_name.[ element_name ] ;
element_name:表示元素名稱,可以使存儲過程名、函數名、變量名和常量名等。
注:程序包中可以定義公有常量和變量,使用的DBMS_OUTPUT.PUT_LINE輸出結果語句,DBMS_OUTPUT是系統定義的包,PUT_LINE是該包的存儲過程。
3、刪除包
使用DEOP PACKAGE語句,如果程序包被刪除,則包體也被自動刪除。如下:
DROP PACKAGE package_name ;
 
 
 
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章