存储过程&存储函数&程序包

-- 创建一个存储过程,or replace 可以省略,省略后仅创建之前没有的
create or replace procedure p
is -- 相当于declare,is也可改成as
cursor cur_emp is select * from emp;
begin
for v_emp in cur_emp loop
dbms_output.put_line(v_emp.empno||'员工姓名'||v_emp.ename);
end loop;
end;

-- 调用存储过程,通过plsql块
declare
begin
p;
end;


-- 创建一个有参存储过程,in用于接受调用程序的值 out返回调用程序值 in out既接受也返回,写在数据类型前面,默认是in
create or replace procedure p2(v_a in number,v_b number,v_c out number,v_d in out number)
is

begin
/*if(v_a>v_b)then
v_c:=v_a;
else
v_c:=v_b;
end if;*/
v_c:=(v_a+v_b);
v_d:=v_d+v_c;
end;

-- 调用有参存储过程,通过plsql块
declare
v_c number;
v_d number:=1;
begin
p2(3,6,v_c,v_d); -- 调用有参存储过程
dbms_output.put_line(v_c);
dbms_output.put_line(v_d);
end;

--创建传游标的存储过程,只能传ref游标
create or replace procedure p3(v_deptno number, cur_emp out sys_refcursor)
is
begin
open cur_emp for select * from emp where deptno=v_deptno;
end;

--通过plsql块调用
declare
type cur_emp_type is ref cursor;
cur_emp cur_emp_type;
v_emp emp%rowtype;
begin
p3(10,cur_emp);
loop
fetch cur_emp into v_emp;
exit when cur_emp%notfound;
dbms_output.put_line(v_emp.empno||'员工姓名'||v_emp.ename);
end loop;
close cur_emp;
end;


-- 创建储存函数,return只需写返回类型,这和java的函数一样
create or replace function f(v_deptno dept.deptno%type) return dept.dname%type
is
v_dname dept.dname%type;
begin
select dname into v_dname from dept where deptno=v_deptno;
return v_dname;
end;

-- 通过sql语句调用
select f(10) from dual;
-- 通过plsql块调用
declare
v_dname dept.dname%type;
begin
v_dname:=f(10);
dbms_output.put_line(v_dname);
end;

-- 创建返回多个值的函数,返回值先封装到ref游标
-- 查询出每个部门的 平均薪资,薪资总和,部门人数,封装到ref游标里面然后返回
create or replace function f2 return sys_refcursor
is
type cur_emp_type is ref cursor;
cur_emp cur_emp_type;
begin
open cur_emp for select deptno,avg(sal),sum(sal),count(1) from emp group by deptno;
return cur_emp;
end;
-- plsql块调用
declare
/*type cur_emp_type is ref cursor;
cur_emp cur_emp_type;*/
cur_emp mp.cur_emp_type; -- 采用程序包mp里面声明好的ref游标类型

v_deptno emp.deptno%type;
v_avgsal emp.sal%type;
v_sumsal number(10,2);
v_count number;
begin
cur_emp:=f2;
loop
fetch cur_emp into v_deptno,v_avgsal,v_sumsal,v_count;
exit when cur_emp%notfound;
dbms_output.put_line( v_deptno||'平均薪资'||v_avgsal||'薪资总和'||v_sumsal||'部门人数'||v_count);
end loop;
close cur_emp;
end;

--程序包 规范+主体
--创建一个程序包,声明一个函数,根据员工编号,查询员工是否存在(个数等于1就存在);
--声明一个过程,根据员工编号查询员工是否存在,存在则返回‘员工姓名’ 否则返回‘该员工不存在’
--创建包规范:注意里面没有begin,而下面的程序包主体是有的,这点要引起注意↓
-- 程序包规范
create or replace package mp
is
v_a number:=666;

type cur_emp_type is ref cursor; -- 声明一种ref游标类型
cursor cur_emp return emp%rowtype; -- return 用于规范游标类型

function f3(v_empno emp.empno%type) return number;
procedure p4(v_empno emp.empno%type,v_msg out varchar2); -- 此varchar2不指定长度
end;
-- 程序包主体
create or replace package body mp
is
v_b number:=777;

cursor cur_emp return emp%rowtype is select * from emp;

function f3(v_empno emp.empno%type) return number
is
v_count number;
begin
select count(1) into v_count from emp where empno=v_empno;
return v_count;
end;

procedure p4(v_empno emp.empno%type,v_msg out varchar2)
is
v_count number;
begin
v_count:=f3(v_empno);
if(v_count=1) then
select ename into v_msg from emp where empno=v_empno;
else
v_msg:='该员工不存在';
end if;
end;
begin
null;
end;
-- plsql块调用程序包里的共有变量
declare
begin
dbms_output.put_line(mp.v_a);
--dbms_output.put_line(mp.f3(7788));
end;
-- sql语句调用程序包的方法
select mp.f3(7788) from dual; --1
-- plsql块调用程序包里的游标
declare
begin
for v_emp in mp.cur_emp loop
dbms_output.put_line(v_emp.ename);
end loop;
end;
-- plsql块调用程序包里的过程
declare
v_msg varchar2(20);
begin
mp.p4(7788,v_msg);
dbms_output.put_line(v_msg);
end;

原文地址:https://www.cnblogs.com/21556guo/p/13573903.html