函数(学习笔记)
函数(存储函数)也是一种较为方便的存储结构,用户定义函数可以被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;
示例四、函数根所员工编号,输出姓名,返回工资
--定义函数根所员工编号,输出姓名,返回工资 CREATE OR REPLACE FUNCTION get_sal(eno NUMBER,eme OUT VARCHAR2) RETURN NUMBER IS v_sal emp.sal%TYPE; BEGIN SELECT sal,ename INTO v_sal,eme FROM emp WHERE empno=eno; RETURN v_sal; EXCEPTION WHEN OTHERS THEN dbms_output.put_line('没有这个员工'); END; --调用 DECLARE v_eno emp.empno%TYPE:=&empno; v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; BEGIN v_sal:=get_sal(v_eno,v_ename); dbms_output.put_line(' 编号:'||v_eno||' 姓名:'||v_ename||' 工资:'||v_sal); END;