函數(存儲函數)也是一種較為方便的存儲結構,用戶定義函數可以被SQL語句或者PL/SQL直接調,函數和過程最大的區別在於,函數可以有返回值,
而過程只能依靠OUT 或者IN OUT返回數據
定義函數語法:
CREATE [OR REPLACE] FUNCTION 函數([參數,...]])
RETURN 返回值類型
[AUTHID [DEFINER | CURRENT_USER]]
AS || IS
[PRAGMA AUTONOMOUS_TRANSACTION;]
聲明部分;
BEGIN
程序部分;
[RETURN 返回值;]
EXCEPTION
導常處理;
END [函數名];
參數中定義參數模式表示過程的數據的接收操作,一般分為IN,OUT,IN OUT 3類
CREATE [OR REPLACE]:表示創建或者替換過程,如果過程存在則替換,如果不存在就創建一個新的
AUTHID子句定義了一個過程的所有者權限,DEFINER(默認)表示定義者權限執行,或者用CURRENT_USER覆蓋程序的默認行為,變為使用者權限
PRAGMA AUTONOMOUS_TRANSACTION:表示過程啟動一個自治事務,自治事務可以讓主事掛起,在過程中執行完SQL後,由用戶處理提交或者回滾自治事務,
然後恢復主事務
和過程的語法基本相似,唯一不同的是在定義函數時候需要有返回值類型(RETURN 返回值類型)聲明
定義一個函數返回系統時間
CREATE OR REPLACE FUNCTION datetime_fun RETURN VARCHAR2 AS BEGIN RETURN to_char(SYSDATE,'yyyy-mm-dd hh24:mi:ss'); END; --調用 DECLARE BEGIN dbms_output.put_line(datetime_fun); END;
帶出輸入和輸出的函數 create or replace function getinfo_fun(eno emp.empno%type, job out emp.job%type) return varchar2 is v_name emp.ename%TYPE; v_count NUMBER; BEGIN SELECT COUNT(eno) INTO v_count FROM emp WHERE empno=eno; IF v_count>0 THEN SELECT ename,job INTO v_name,job FROM emp WHERE empno=eno; END IF; RETURN v_name; end getinfo_fun; --調用 DECLARE v_id emp.empno%TYPE:=&empno; v_name emp.ename%TYPE; v_job emp.job%TYPE; BEGIN v_name:=getinfo_fun(v_id,v_job); dbms_output.put_line('員工編號是:'||v_id||' 姓名:'||v_name||' 職位:'||v_job); END;
示例一、定義函數通過員工編號來查詢員工的工資
CREATE OR REPLACE FUNCTION GET_SAL_FUN(F_NO EMP.EMPNO%TYPE) RETURN NUMBER AS V_SAL EMP.SAL%TYPE; BEGIN SELECT SAL INTO V_SAL FROM EMP WHERE EMPNO = F_NO; RETURN V_SAL; END; --調用 DECLARE v_id emp.empno%TYPE:=&empno; v_sal emp.sal%TYPE; BEGIN v_sal:=get_sal_fun(v_id); dbms_output.put_line('員工編號:'||v_id||' 的工資為: '||v_sal); END;
第二種
-使用過程來調用 CREATE OR REPLACE PROCEDURE invoke_proc AS v_id emp.empno%TYPE:=&empno; v_sal emp.sal%TYPE; BEGIN v_sal:=get_sal_fun(v_id); dbms_output.put_line('員工編號:'||v_id||' 的工資為: '||v_sal); END; EXEC invoke_proc ;
第三種
使用sql語句來調用 SELECT get_sal_fun(&v_id) FROM dual;
參數模式
IN模式
示例一、定義函數使用IN
CREATE OR REPLACE FUNCTION in_fun( f_b VARCHAR2 DEFAULT 'Java開發實戰經典', --默認的參數模式為in f_a IN VARCHAR2 DEFAULT '好好學習' --明確定義IN參數模式 ) RETURN VARCHAR2 AS BEGIN RETURN f_a; END; 執行 DECLARE v_a VARCHAR2(50); v_b VARCHAR2(50); BEGIN v_b:=in_fun(v_a); dbms_output.put_line(v_b); dbms_output.put_line(SQLERRM); END; 結果: 好好學習 ORA-0000: normal, successful completion
OUT模式
示例二、定義函數使用OUT
CREATE OR REPLACE FUNCTION out_fun( f_a OUT Varchar2, f_b OUT VARCHAR2 ) RETURN VARCHAR2 AS BEGIN f_a:='Java開發實戰經典'; f_b:='Oracle開發實戰經典'; RETURN f_b; END; --調用 DECLARE v_a VARCHAR2(100); v_b VARCHAR2(100); v_result VARCHAR2(100); BEGIN v_result:=out_fun(v_a,v_b); dbms_output.put_line(v_result); dbms_output.put_line(SQLERRM); END;
示例三、通過函數完成部門增加
CREATE OR REPLACE FUNCTION dept_inser_fun( f_dno dept.deptno%TYPE, f_dname dept.dname%TYPE, f_loc dept.loc%TYPE ) RETURN NUMBER AS v_count NUMBER; BEGIN SELECT COUNT(deptno) INTO v_count FROM dept WHERE deptno=f_dno; IF v_count>0 THEN RETURN -1; --返回失敗 ELSE INSERT INTO dept(deptno,dname,loc)VALUES(f_dno,f_dname,f_loc); COMMIT; RETURN 0; END IF; END; --調用 DECLARE v_result NUMBER; BEGIN v_result:=dept_inser_fun(&deptno,'&dname','&loc'); IF V_RESULT = 0 THEN DBMS_OUTPUT.PUT_LINE('新部門增加成功'); ELSE DBMS_OUTPUT.PUT_LINE('新部門增加失敗'); END IF; END; VAR v_sal NUMBER; CALL get_sal_fun(&v_id) INTO v-sal; print v_sal;