【Oracle基础】存储过程和存储函数

一、基础介绍

  • 存储过程和函数也是数据库对象,是存储在数据库中的被命名的PLSQL块,供所有用户程序调用完成特定功能的子程序。
  • 存储过程类似java中的void方法,主要用途是功能的处理,存储该函数类似非void方法,需要return返回值。

二、存储过程

(一) 创建和调用

语法

CREATE [OR REPLACE] PROCEDURE 过程名
[(参数名1  IN|OUT|IN OUT 参数值类型 [DEFAULT 默认值]),
(参数名2  IN|OUT|IN OUT 参数值类型[DEFAULT 默认值])...]
AS|IS
	[变量名 变量类型[:=初始值];    --声明变量部分 ]
BEGIN
	执行部分;
[EXCEPTION
	异常错误处理部分;]
END;

1.无参的存储过程

1)创建

--创建存储过程(无参)
CREATE OR REPLACE 
PROCEDURE first_proc2 is--
BEGIN
	DBMS_OUTPUT.PUT_LINE('我是过程2');--打印内容
	DBMS_OUTPUT.PUT_LINE('hello everyone!');
END;

2)调用

BEGIN
	first_proc2;
end;

2.带输入参数的存储过程in

1)创建

create or replace procedure proc_inparams 
(v_empno in EMPNEW.EMPNO%TYPE)--名称是v_empno的In类型的参数,TYPE与emp_1表的empno字段相同
IS
begin
	--根据员工号删除指定员工信息
	delete from EMPNEW where empno=v_empno;--一般不用在程序中commit和rollback
	--判断是否成功
	if SQL%NOTFOUND then
		-- -20000~20999之间
		RAISE_APPLICATION_ERROR(-20008,'指定删除的员工不存在');--内置的存储过程,用于在子程序中指定错误的自定义信息,错误号和错误提示内容可以自定义
	ELSE
		DBMS_OUTPUT.PUT_LINE('删除成功');
	END IF;

end;

2)调用

BEGIN
	PROC_INPARAMS(1234);--调用时传参
end;
DECLARE
	dpn number:=1234;
BEGIN
	PROC_INPARAMS(dpn);
end;

3.带输出过程的存储过程out

1)创建

create or replace procedure proc_outparams
(v_deptno in number,v_avgsal out number,v_cnt out number)
AS
BEGIN
	select avg(sal),count(*) into v_avgsal,v_cnt --参数变量赋值into
	from EMP
	where deptno=v_deptno;
EXCEPTION
	when NO_DATA_FOUND THEN
		DBMS_OUTPUT.put_line('无此部门');
	when others THEN
		DBMS_OUTPUT.put_line(SQLERRM);
END;

2)调用

DECLARE
	v_avgsalary number;--声明两个变量用于接收out参数
	v_count number;
BEGIN
	PROC_OUTPARAMS(10,v_avgsalary,v_count);--位置传值,声明的变量按照顺序对应接收out参数
	DBMS_OUTPUT.put_line('平均工资:'||v_avgsalary);
	DBMS_OUTPUT.put_line('总人数:'||v_count);
end;

4.带输入输出过程的存储过程in out

1)创建

create or replace procedure proc_inoutparams
(v_num1 in out number,v_num2 in out number)
as
	v_temp number:=0;--声明一个叫v_temp的变量,type是NUMBER,赋值0
BEGIN
	--交换两个数
	v_temp:=v_num1;
	v_num1:=v_num2;
	v_num2:=v_temp;

end;

2)调用

DECLARE
	v_n1 number:=5;--声明两个变量用于接收参数
	v_n2 number:=8;
BEGIN
	PROC_INOUTPARAMS(v_n1,v_n2);--声明的变量按照顺序对应接收in out参数
	DBMS_OUTPUT.put_line('v_n1:'||v_n1);
	DBMS_OUTPUT.put_line('v_n2:'||v_n2);
end;

(二) 删除

drop procedure "first_proc";--过程名区分是否有引号

三、存储函数

(一) 创建和调用

语法

CREATE [OR REPLACE] FUNCTION 函数名
[(参数名1  IN|OUT|IN OUT 参数值类型 [DEFAULT 默认值]),
(参数名2  IN|OUT|IN OUT 参数值类型 [DEFAULT 默认值])...]
RETURN 返回值类型--比过程多的部分
AS|IS
	[变量名 变量类型[:=初始值];    --声明变量部分 ]
BEGIN
	执行部分;
[EXCEPTION
	异常错误处理部分;]
END;

1.无参的存储函数

1)创建

CREATE OR REPLACE function "first_func2" 
return VARCHAR2
iS
BEGIN
	DBMS_OUTPUT.PUT_LINE('我是函数2');
	return 'hello,everyone';--对应之前的类型
END;

2)调用

BEGIN
	dbms_output.put_line(first_func2);
end;

2.带输入参数的存储函数in

1)创建

create or replace function func_inparams
(v_deptno in number)
return NUMBER
is
	v_sumsal number;--声明变量
BEGIN
	--根据部门编号返回部门总工资
	select sum(sal) into v_sumsal from emp where DEPTNO=v_deptno;--变量赋值
	return v_sumsal;--返回变量
EXCEPTION
	when no_data_found THEN
		dbms_output.put_line('无此部门');
	when others THEN
		DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;

2)调用

BEGIN
	dbms_output.put_line('部门工资总和:'||FUNC_INPARAMS(10));
end;

3.带输出过程的存储函数out

1)创建

create or replace function func_outparams
(v_empno in EMP.EMPNO%type, v_name out EMP.ENAME%type,v_sal out EMP.SAL%type )
return number
AS
	v_yasal number;
BEGIN
	--根据员工号输出员工姓名和工资,并返回员工的年收入
	select ename,sal,(sal+nvl(comm,0))*12 into v_name,v_sal,v_yasal
	from EMP
	where empno=v_empno;
	return v_yasal;
EXCEPTION
	when no_data_found THEN
		dbms_output.put_line('无此员工');
	when others THEN
		DBMS_OUTPUT.PUT_LINE(SQLERRM);	
END;

2)调用

DECLARE
	v_name EMP.ENAME%type;--声明两个变量用于接收out参数
	v_sal EMP.SAL%type;
	v_yasal number;
BEGIN
	v_yasal:=FUNC_OUTPARAMS(7369,v_name,v_sal);
	dbms_output.put_line('姓名'||v_name||'的工资是'||v_sal||',年总收入是:'||v_yasal);
end;

4.带输入输出过程的存储函数in out

1)创建

create or replace function func_inoutparams
(n1 in out number,n2 in out number)
return NUMBER
AS
BEGIN
	n1:=n1*n1;
	n2:=n2*n2;
	return n1+n2;
end;

2)调用

DECLARE
	v_n1 number :=5;
	v_n2 number :=8;
BEGIN
	dbms_output.put_line(v_n1||'和'||v_n2||'的和是:'||FUNC_INOUTPARAMS(v_n1, v_n2));--此时v_n1和v_n2已经参与函数计算
end;

(二) 删除

drop function "first_func";

四、使用DEFAULT默认值

1.单个参数

--------------------------------求部门的年收入----------------------
--创建
CREATE OR REPLACE 
function func_defa
(v_deptno in number DEFAULT 10)
return NUMBER
AS
	v_deptysal number;
BEGIN
	select sum(sal+nvl(comm,0))*12 into v_deptysal
	from emp where deptno=v_deptno;
	return v_deptysal;
EXCEPTION
	when NO_DATA_FOUND THEN
		DBMS_OUTPUT.put_line('没有此部门');
	when others THEN
		DBMS_OUTPUT.put_line(SQLERRM);
end;


--调用
BEGIN
	dbms_output.put_line('部门年收入总和:'||FUNC_DEFA);--使用默认值,不用传参
	dbms_output.put_line('部门年收入总和:'||FUNC_DEFA(20));--不用默认值,需要传参
end;

2.多个参数

---------------------------求部门的年收入---------------------
--创建
CREATE OR REPLACE 
function func_defa2
(v_deptno in number DEFAULT 10,v_test in number)
return NUMBER
AS
	v_deptysal number;
BEGIN
	select sum(sal+nvl(comm,0))*12 into v_deptysal
	from emp where deptno=v_deptno;
	DBMS_OUTPUT.put_line('测试:'||v_test);
	return v_deptysal;
EXCEPTION
	when NO_DATA_FOUND THEN
		DBMS_OUTPUT.put_line('没有此部门');
	when others THEN
		DBMS_OUTPUT.put_line(SQLERRM);
end;

--调用
BEGIN
	--dbms_output.put_line('部门年收入总和:'||FUNC_DEFA2(,888));--第一个参数省略时,位置传值,报错,不能这样传
	dbms_output.put_line('部门年收入总和:'||FUNC_DEFA2(v_test=>888));--名称传值,关联符号=>
end;

五、比较

1.关键字

创建过程:procedure
创建函数:function

2.调用方式

存储过程使用独立的调用语句

begin
	proc1
end;

存储函数以表达式方式调用

declare
	v_result NUMBER;
begin
	v_result:=func1;
end;

4.return返回值

存储函数通过return语句返回函数值,存储过程则没有

5.用途

存储过程的目的是完成一系列的数据处理;存储函数的目的是获得函数返回值。

6.参数

过程和函数都可以有一个或多个out输出函数。
存储过程没有return语句,但是可以通过out参数来实现返回值。
一般原则,如果只有一个返回值,用存储函数处理

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