您好,欢迎访问一九零五行业门户网

Oracle存储过程详解(引用)+补充

一、过程 (存储过程) 过程是一个能执行某个特定操作的子程序。使用create or replace创建或者替换保存在数据库中的一个子程序。 示例1: 声明存储过程,该过程返回dept表行数 declare procedure getdeptcount as deptcount int;begin select count(*) into d
一、过程 (存储过程)过程是一个能执行某个特定操作的子程序。使用create or replace创建或者替换保存在数据库中的一个子程序。
示例1:声明存储过程,该过程返回dept表行数
declareprocedure getdeptcountasdeptcount int;beginselect count(*) into deptcount from dept;dbms_output.put_line('dept表的共有记录数:'||deptcount);end getdeptcount;begingetdeptcount[()];end;
注意:此存储过程getdeptcount只在块运行时有效。
示例2:创建不带参数的存储过程,该过程返回dept表行数
create or replace procedure getdeptcountas | isdeptcount int;beginselect count(*) into deptcount from dept;dbms_output.put_line('dept表共有'||deptcount||'行记录');end [getdeptcount];
当我们创建的存储过程没有参数时,在存储过程名字后面不能有括号。在as或者is后至begin之前是声明部分,存储过程中的声明不使用declare关键字。同匿名pl/sql块一样,exception和声明部分都是可选的。
当我们创建的过程带有错误时,我们可以通过select * from user_errors查看,或者使用show errors [ procedure proc_name]查看。
使用以下代码可以执行存储过程:
begingetdeptcount;end;以上存储过程还可以通过以下代码来简化调用:exec getdeptcount[;] call getdeptcount();
注意:
并不是所有的存储过程都可以用这种方式来调用定义无参存储过程时,存储过程名后不能加()在块中或是通过exec调用存储过程时可以省略()通过call调用无参存储过程必须加上()示例3:创建带有输入参数的存储过程,该过程通过员工编号打印工资额
create or replace procedure getsalarybyempno(eno number) --参数的数据类型不能指定长度assalary emp.sal%type;beginselect sal into salary from emp where empno=eno;dbms_output.put_line(eno||'号员工的工资为'||salary);exceptionwhen no_data_found thendbms_output.put_line('没有找到该编号的员工');end;
当定义的存储过程含有参数时,参数的数据类型不能指定长度。参数还有输入和输出之分,本例中没有指定,默认情况为输入参数,也可显示的指定某个参数是输入参数,如(eno in number)。同示例1不同,该例中加入了异常处理。同示例1类似可以使用下面的两种方式调用存储过程:
begin
getsalarybyempno(7788);
end;
或者
exec getsalarybyempno(7788);  或者
call getsalarybyempno(7788);
但是如果传给一个存储过程的参数是变量时,必须使用begin  end块,如下:
declareno emp.empno%type;beginno:=7788;getsalarybyempno(no);end;
如果某个包中含有常量,也可以通过如下的方式调用:
exec getsalarybyempno(constantpackage.no);
但这种方式不能再使用call调用。
示例4:创建含有输入和输出参数的存储过程,该过程通过员工编号查找工资额,工资额以输出参数返回
create or replace procedure getsalarybyempno(eno in number,salary out number)asbeginselect sal into salary from emp where empno=eno;exceptionwhen no_data_found thendbms_output.put_line('没有找到该编号的员工');end;
当过程中含有输出参数时,调用时必须通过begin  end块,不能通过exec或call调用。如:
declaresalary number(7,2);begingetsalarybyempno(7788,salary);dbms_output.put_line(salary);end;
示例5:创建参数类型既是输入参数也是输出参数的过程
create or replace procedure getsalarybyempno(nosalary in out number)asbeginselect sal into nosalary from emp where empno=nosalary;exceptionwhen no_data_found thendbms_output.put_line('没有找到该编号的员工');end;
调用如下:
declareno number(7,2);beginno:=7788;getsalarybyempno(no);dbms_output.put_line(no);end;
示例6:创建带有默认值的过程
create or replace procedure addemp(empno number,ename varchar2,job varchar2 :='clerk',mgr number,hiredate date default sysdate,sal number default 1000,comm number default 0,deptno number default 30)asbegininsert into emp values(empno,ename,job,mgr,hiredate,sal,comm,deptno);end;
调用如下:
exec addemp(7776,'zhangsan','coder',7788,'06-1月-2000',2000,0,10); --没有使用默认值exec addemp(7777,'lisi','coder',7788,'06-1月-2000',2000,null,10); --可以使用null值exec addemp(7778,'wangwu',mgr=>7788); --使用默认值exec addemp(mgr=>7788,empno=>7779,ename=>'sunliu'); --更改参数顺序
示例7:使用nocopy编译提示
当参数是大型数据结构时,如集合、记录和对象实例,把它们的内容全部拷贝给形参会降低执行速度,消耗大量内存。为了防止这样的情况发生,我们可以使用 nocopy提示来让编译器按引用传递方式给in out模式的参数。
declaretype deptlist is table of varchar2(10);dlist deptlist:=deptlist('coresun','coresun','coresun','coresun');procedure my_proc(d in out nocopy deptlist)as...
注意:nocopy只是一个提示,而不是指令。即使有时候我们使用了nocopy,但编译器有可能仍然会进行值拷贝。通常情况下nocopy是可以成功的。
二、维护过程1、删除存储过程
drop procedure proc_name;
2、查看过程状态
select object_name,status from user_objects where object_type='procedure';
3、重新编译过程
alter procedure proc_name compile;
4、查看过程代码
select * from user_source where type='procedure';
三、参数的理解-- 输出参数不可以修改解决的方法有两种
--1 把参数改成输入参数 
--2 就是参数改成 可输入输出的参数;
调用过程的 三个方式
1 就是使用call
在只用call方式调用函数的时候,必须加要括号,有参数,还要加参数值
这个方式在命令窗口,调用过程,将不会出现输入的数据.
2 就是使用exec 命令,进行命令调用过程, 使用命令,就必须在命令行里面输入
过程名,这个命令窗口中,可加可不加() ,如果有参数的,就一定要加,还有参数值,参数值的类型要与
变量类型相同.
3 在语句块中进行调用过程,这个方式和命令模式类似,他们都是可要可不要(),
-- 在2 和 3 中的 没有括号的情况是,过程没有参数 ,如果有,就必须要有()
输出参数的特点
1 一个过程中,如果有输出参数(out 参数),在调用过程的使用,也要传入一个参数, 这个参数可以不用在调用的地方
进行赋值,就直接传入一个声明好的一个变量,用来接受存储过程中的输出参数的值(out 参数)
2 输入参数 值不可以改变在过程中,
注意: 在存储过程中,他的参数类型不可以设置它的大小 ; 
例如;
create or replace procedure hello(p_name in varchar2(12),p_age out number(10,2))isbegin
如果有输出参数就必须有有一个参数进行接收 ;
create or replace procedure hello(p_name in varchar2,p_age out emp.sal%type)isbeginselect emp.sal + 3131 into p_age from emp where empno = 7788 ;dbms_output.put_line( p_age);end ;
--------- 块中调用方法
declarev_nanme varchar2(12);v_age number (12,2);beginhello (v_nanme,v_age);dbms_output.put_line(v_age);end ;
-- 在这个过程中 传入的v_age 就是接受 存储过程输出参数的值 ; 类似于java的中的返回值
-- 理解 in out 参数
create or replace procedure hello1 (p_name in out emp.ename%type)isbegin-- select emp.ename into p_name from emp ;p_name:='a;sk , ' || p_name ;end ;--------------------------------------------------------------------------declarev_nanme varchar2(12);begin v_nanme:='12312';hello1(v_nanme);
补充:sqlplus中执行含有输出参数为游标的存储过程实例6:
sqlplus创建存储过程,使用如下:
sql>create or replace procedure test1(rcursor out sys_refcursor) asbegin open rcursor for select decode(row_number() over(partition by deptno order by ename), 1, deptno, null) deptno, t.ename from scott.emp t;end;/
--使用sqlplus执行上面创建的带有游标输出参数的存储过程
sql> var cur refcursorsql> exec test1(:cur);pl/sql procedure successfully completed.sql> print cur; deptno ename---------- ---------- 10 clark king miller 20 adams ford jones scott smith 30 allen blake james deptno ename---------- ---------- martin turner ward14 rows selected.
其它类似信息

推荐信息