存储过程在数据库开发的过程中使用比较频繁,它也有着普通sql语句不可替代的作用,可以有效的提程序的执行效率。存储过程可以简单的理解为在数据库中执行的某种带特定功能的程序,其中包含一条或多条sql语句,它的语法大体与PLSQL相同,也有其自身的不同。
首先我们创建一张表
create table class( id int not null,--班级id class_name varchar2(20)--班级名字 );
创建一个存储过程
create or replace procedure findclass --创建或修改存储过程,存储过程名为findclass as totalClass number(1); --创建一个数字类型的变量,totalClass begin --存储过程开始 select count(*) into totalClass from class; --把count计数出来的数量 通过into赋值给totalClass变量 DBMS_OUTPUT.put_line('总班级数'||totalClass); --数据库输出数量 end findclass; --存储过程结束
执行存储过程,这里我用的是plsqldev这个工具,所以有三种执行方法,其中有两种是代码执行,一种是工具执行
--执行存储过程方法1::call call findclass(); --执行存储过程方法2:begin end begin findclass(); end;
执行结果显示在output窗口
执行存储过程的第三种方法,也是开发过程中最常用的方法,就是plsqldev工具自带的test方法执行存储过程,该方法可以对存储过程进行断点调试
在plsqldev中所有的存储过程都可以在Procedures文件夹中找到
找到需要执行的存储过程右键出现选择菜单
点击test出现如下界面
点击单步运行,进入断点模式,点击单步当执行到findclass时,会进入到代码断点界面,在Variable输入变量名后可跟在Value跟踪变量值的变化
特别说明,如果单步断点模式无法进行,可在右键test之前先右键选择Add debug information即可。
以上就是我们执行的一个最简单的存储过程,但是在实际开发过程中,我们是会带有参数条件的存储过程。
存储过程的参数有三种
- in 输入参数,作为存储过程中的sql的查询条件使用
- out输出参数,作为存储过程查询结果输出
- inout输入输出参数,当一个变量既要作为条件输入,也要作为结果输出的时候,可以用此类型参数
使用语法
--param 表示参数名,in表示参数类型为输入,type表示参数类型 param in type
下面就把findclass这个存储过程做一定的修改
--创建或修改存储过程,存储过程名为findclass,输入参数为classId,输出className create or replace procedure findclass(classId in int,className out varchar2) as --存储过程开始 begin --把查询出来的class_name 赋值给输出变量className,查询条件为classId select class_name into className from class where id = classId; --数据库输出数量,这句输出只是方便测试,真正输出的值是out的值 DBMS_OUTPUT.put_line('班级名:'||className); --存储过程结束 end findclass;
右键选择存储过程test,因为存储过程带有参数,需要输入参数
单步过程同样可以监控参数变化
当执行到代码第8行的时候,可以监控到输出参数classname为J130,这里特别说明下,在存储过程中需要监控的参数需要自己输入到监控界面Variable处。
执行完成,输出结果J130
在实际项目中,我们也会遇到需要同时输入,输出几个参数的情况
首先,在建立一张学生表
create table student( id int not null,--学生id student_name varchar2(20),--学生姓名 fk_class int --班级外键 );
创建一个多参数的存储过程,通过班级ID查询出班级名字及该班级所有的学生,本来最简单的方法就是一个连表查询就OK了,在这里我们模拟一下稍微复杂点的情况,使用游标来进行操作。
--创建或修改存储过程,存储过程名为findclass,输入参数为classId,输出className create or replace procedure findclass(classId in int,classStudents out sys_refcursor,className out varchar2) as --定义一个游标的方式有多种,可以显示定义CURSOR cursor_name is select * from table,也可以定义动态游标,游标关键词CURSOR TYPE ref_cursor_type IS REF CURSOR; --定义一个动态游标 students ref_cursor_type; --定义班级集合为一个游标类型 student_row student%rowtype; --定义班级类型,类型为student表行类型 --存储过程开始 begin --把查询出来的class_name 赋值给输出变量className,查询条件为classId select class_name into className from class where id = classId; --打开游标并赋值 open students for select * from student where fk_class =classId; --把查询结果赋值给输出变量,实际上可以直接open classStudents for select * from student where fk_class =classId; classStudents := students; --循环输出游标,循环有三种方式,for in循环,fetch循环,while循环 --fetch循环 loop fetch classStudents into student_row; --当循环到空跳出循环 EXIT WHEN classStudents%NOTFOUND; DBMS_OUTPUT.put_line('学生名:'); end loop; DBMS_OUTPUT.put_line('班级名:'||className); --存储过程结束 end findclass;
输出结果
这里特别说明,如果查询中有多个变需要into赋值,只需要写一个into就可以了
--这样赋值是错误的 select student_name into studentName,class_name into className from class; --正确写法,into前面写table列名,后面写需要赋值的变量名,顺序要对 select student_name,class_name into studentName,className from class;