Oracle已經提供了許多可用函數,但是在特定需求上,我們還是需要設計滿足要求的自定義函數。得空收集各類資料整理,還需多多使用加以熟悉。
一、函數語法
Create [or replace] function funtionName(parameter1 mode1 dataType1,parameter2 mode2 dataType2,….)
Return returnDataType
Is/as
--定義使用變量、返回變量;
Begin
Function_body;
Return expression;
End functionName;--結束函數的聲明,也可以直接寫end不加函數名。
說明:
function_name:用戶定義的函數名。函數名必須符合標示符的定義規則,對其所有者來說,該名在數據庫中是唯一的。
parameter:用戶定義的參數。用戶可以定義一個或多個參數。
mode:參數類型。參數的模式有3種:(如果沒有註明, 參數默認的類型爲 in),in: 爲只讀模式, 在函數中, 參數的值只能被引用, 不能被改變;out: 爲只寫模式, 只能被賦值, 不能被引用;in out: 可讀可寫。
dataType:用戶定義參數的數據類型。
returnDataType:表示返回值類型。
Function_body:函數主體由pl/sql語句構成。
expression:函數返回expression表達式的值。
注意:函數可以沒有輸入輸出參數,但一定要有返回(return)的數據類型,因此必須有內部變量存儲return的數據;
二、實例
根據輸入的數字,返回兩個數的和,若除數爲0,則拋出自定義異常。
create or replace function testdivision(js1 in number, js2 in number)
return number is
v_re number;
customize_exp EXCEPTION; --自定義異常
begin
if js2 = 0 then
raise customize_exp;
--raise_application_error(-20006,'不能除0');
else
v_re := js1 / js2;
return v_re;
end if;
exception
--捕獲異常
when customize_exp then
dbms_output.put_line('customize error!'); --打印參數
raise_application_error(-20006, '不能除0'); --異常提示
when others then
return 0;
end;
--刪除函數
DROP FUNCTION testdivision;
--查看當前用戶無效函數
SELECT object_name FROM user_objects WHERE status='INVALID' AND object_type='FUNCTION';
--查看函數代碼
SELECT * FROM user_source WHERE name=upper('testdivision');
三、執行動態SQL
在一般的sql操作中,sql語句基本上都是固定的,如:SELECT t.empno,t.ename FROM scott.emp t WHERE t.deptno = 20;但有的時候,從應用的需要或程序的編寫出發,都可能需要用到動態SQl,如:當 from 後的表 不確定時,或者where 後的條件不確定時,都需要用到動態SQL。例如根據表名查詢記錄數:
create or replace function count_rows(table_name in varchar2,owner in varchar2 default null)
return number authid current_user IS
num_rows number;
stmt varchar2(2000);
begin
--獲取某表的記錄條數
if owner is null then
stmt := 'select count(*) from "' || table_name || '"';
else
stmt := 'select count(*) from "' || owner || '"."' || table_name || '"';
end if;
execute immediate stmt
into num_rows;
return num_rows;
exception
when others then
return 0;
end;
執行動態語句的話需要顯式的授權,加上AUTHID CURRENT_USER。
AUTHID DEFINER (定義者權限):指編譯存儲對象的所有者。也是默認權限模式。
AUTHID CURRENT_USER(調用者權限):指擁有當前會話權限的模式,這可能和當前登錄用戶相同或不同(alter session set current_schema 可以改變調用者Schema)。
EXECUTE IMMEDIATE用法例子:
1. 給動態語句傳值(USING 子句)
declare
l_depnam varchar2(20) := 'testing';
l_loc varchar2(10) := 'Dubai';
begin
execute immediate 'insert into dept values (:1, :2, :3)'
using 50, l_depnam, l_loc;
commit;
end;
2. 從動態語句檢索值(INTO子句)
declare
l_cnt varchar2(20);
begin
execute immediate 'select count(1) from emp'
into l_cnt;
dbms_output.put_line(l_cnt);
end;
3. 動態調用例程.例程中用到的綁定變量參數必須指定參數類型.黓認爲IN類型,其它類型必須顯式指定
declare
l_routin varchar2(100) := 'gen2161.get_rowcnt';
l_tblnam varchar2(20) := 'emp';
l_cnt number;
l_status varchar2(200);
begin
execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
using in l_tblnam, out l_cnt, in out l_status;
if l_status != 'OK' then
dbms_output.put_line('error');
end if;
end;
4. 將返回值傳遞到PL/SQL記錄類型;同樣也可用%rowtype變量
declare
type empdtlrec is record (empno number(4),ename varchar2(20),deptno number(2));
empdtl empdtlrec;
begin
execute immediate 'select empno, ename, deptno '||'from emp where empno = 7934'
into empdtl;
end;
5. 傳遞並檢索值.INTO子句用在USING子句前
declare
l_dept pls_integer := 20;
l_nam varchar2(20);
l_loc varchar2(20);
begin
execute immediate 'select dname, loc from dept where deptno = :1'
into l_nam, l_loc
using l_dept ;
end;