游标是构建在PL/SQL中用来查询数据获取记录集的指针它让开发者 一次访问结果集中一行记录 在oracle中提供了两种游标 静态游标 ref游标
静态游标静态游标是在编译的时候就被确定然后把结果集复制到内存中 静态游标又分为两种隐式游标和显示游标
ref游标ref游标是在运行的时候加载结果集
先来看看静态游标中的隐式游标 在PL/SQL中为所有的SQL数据操纵语句(包括返回一行的select)隐式声明游标 称为隐式游标主要原因是用户不能直接命名和控制此类游标当用户在PL/SQL 中使用数据操纵语句(DML)时oracle预先定义一个名称为SQL的隐式游标通过 检查隐式游标的属性获取与最近执行的SQL语句相关信息 在执行DML语句之后隐式游标属性返回信息隐式游标属性包括 %found %notfound %rowcount %isopen
%found 只有DML语句影响一行或多行时%found属性才返回true declare num number; begin update emp set empno= where empno=; if sql%found then dbms_outputput_line(存在记录); else dbms_outputput_line(不存在记录); end if; end;
%notfound %notfound属性作用正好跟%found属性相反如果DML语句没有影响任何行数 则%notfound属性返回true declare begin delete from emp where empno=; if sql%notfound then dbms_outputput_line(删除失败); end if; end;
%rowcount %rowcount属性返回DML语句影响的行数如果DML语句没有影响任何行数 则%rowcount属性将返回 declare num number; begin update emp set empno= where empno=; if sql%rowcount= then dbms_outputput_line(不存在记录); else dbms_outputput_line(存在记录); end if; end;
%isopen %isopen属性判断SQL游标是否已经打开在执行SQL语句之后oracle自动关闭SQL 游标所以隐式游标的%isopen属性始终为false
在PL/SQL中向标准的select语句增加单独的into子句就可以将从表或视图中查询 记录赋予变量或行变量需要注意的是select into 语句结果必须有且只能有一行 如果查询没有返回行PL/SQL将抛出no_data_found异常如果查询返回多行则抛出 too_many_rows 异常如果抛出异常则停止执行控制权转移到异常处理部分(没有 异常处理则程序中断)在引发异常时将不使用属性%found%notfound%rowcount来查明DML语句是否 已影响了行数 declare num number; begin select empno into num from emp where empno=; if sql%rowcount= or sql%notfound then dbms_outputput_line(不存在记录); else dbms_outputput_line(存在记录); end if; end;
显示游标 显示游标是由用户显示声明的游标根据在游标中定义的查询查询返回的行集合可以 包含零行或多行这些行称为活动集游标将指向活动集中的当前行 显示游标的操作过程使用显示游标的个步骤 ()声明游标 ()打开游标 ()从游标中获取结果集 ()关闭游标 cursor cursor_name [(parameter[parameter])] [return return_type] is select_statement; cursor_name 指游标的名称 parameter 为游标指定输入参数 return_type 定义游标提取行的行类型 select_statement 为游标定义查询语句 open 游标名称 fetch 从游标中提取行 close 关闭游标
打开游标执行游标中定义的查询语句绑定输入参数将游标指针指 向结果集的BOF位置 open cursor_name [parameters]
fetch 在打开游标之后可以从游标中提取记录 fetch cursor_name into variable_name; fetch 是提取结果集中一行记录存储在变量中每次提取之后结果集指针 就向前移动一行
close 在处理游标中的所有行之后必须关闭游标以释放分配给游标的所有资源 close cursor_name 用户可以通过检查游标属性来确定游标的当前状态显示游标的属性如下 %found如果执行最后一条fetch语句成功返回行则%found属性为true %notfound如果执行最后一条fetch语句未能提取行则%notfound属性为true %isopen:如果游标已经打开则返回true否则返回false %rowcount返回到目前为止游标提取的行数%rowcount为数字类型属性在第一 次获取之前%rowcount为零当fetch语句返回一行时则该数加 declare info emp%rowtype; cursor my_cur is select * from emp where empno=; begin open my_cur; dbms_outputput_line(my_cur%rowcount); loop if my_cur%isopen then fetch my_cur into info; exit when my_cur%notfound; dbms_outputput_line(infoempno); dbms_outputput_line(my_cur%rowcount); end if; end loop; close my_cur; end;
使用显示游标删除或更新 使用游标时如果处理过程中需要删除或更新在定义游标查询语句时 必须使用selectfor update语句而在执行delete或update时使用 where current of 子句指定游标当前行 cursor cursor_name is select_statement for update[of column] wait/nowait 在使用for update 子句声明游标之后可以使用以下语法更新行 update table_name set column_name=column_value where current of cursor_name; update命令中使用的列必须出现在for update of 子句中 select 语句必须只包括一个表而且delete和update语句只有在打开游标并且提取 特定行之后才能使用 declare cursor cur_emp is select * from emp where sal< for update of sal; num emp%rowtype; begin open cur_emp; loop fetch cur_emp into num; exit when cur_emp%notfound; update emp set sal= where current of cur_emp; end loop; close cur_emp; end;
带参数的显示游标 PL/SQL中允许显示游标接受输入参数用于声明带参数的显示游标语法 cursor cursor_name[<param_name> data_type] [return <return type>] is select_statement declare dept_num empdeptno%type; emp_num empempno%type; emp_nam empename%type; cursor emp_cur(deptparam number) is select empnoename from emp where deptno=deptparam; begin dept_num :=&部门编号; open emp_cur(dept_num); loop fetch emp_cur into emp_numemp_nam; exit when emp_cur%notfound; dbms_outputput_line(emp_num|| ||emp_nam); end loop; close emp_cur; end;
可以使用循环游标来简化显示游标循环游标隐式打开显示游标(不需要open) 自动从结果集提取记录然后处理完所有记录自动关闭游标循环游标自动创建 %rowtype类型的变量并将此变量用做记录的索引 循环游标语法如下 for record_index in cursor_name record_index是PL/SQL自动创建的变量此变量的属性声明为%rowtype类型作用 域for循环之内 循环游标的特性有 从游标中提取所有记录之后自动关闭游标 提取和处理游标中每一条记录 提取记录之后%notfound属性为true则退出循环如果未有结果集则不进入循环 declare cursor emp_cur is select * from emp; begin for temp in emp_cur loop dbms_outputput_line(tempename); end loop; end; 循环游标自动打开提取关闭只适用于静态游标
ref游标 隐式游标和显示游标都是静态定义的它们在编译的时候结果集就已经被确定 如果想在运行的时候动态确定结果集就要使用ref游标和游标变量
创建ref游标需要两个步骤 声明ref cursor类型 声明 ref cursor类型变量 语法如下 type ref_cursor_name is ref cursor [return record_type] 其中return 用于指定游标提取结果集的返回类型有return表示是强类型ref游标 没有return表示是弱类型的游标弱类型游标可以提取任何类型的结果集 定义游标变量之后就可以在PL/SQL执行部门打开游标变量 open cursor_name for select_statement; declare type emp_cur is ref cursor; my_cur emp_cur; num number; selection varchar():=&请输入编号; begin if selection= then dbms_outputput_line(员工信息); open my_cur for select deptno from emp; elsif selection= then dbms_outputput_line(部门信息); open my_cur for select deptno from dept; else dbms_outputput_line(请输入员工信息()或门部信息()); end if; fetch my_cur into num; while my_cur%found loop dbms_outputput_line(num); fetch my_cur into num; end loop; close my_cur; end;
在PL/SQL中可以执行动态SQL语句execute immediate 语句只能语句处理返回单行 或没有返回的SQL语句ref游标则可以处理返回结果集的动态SQLref游标的声明 方法与普通ref游标相同只是在open时指定了动态SQL字符串 open cursor_name for dynamic_select_string [using bind_argument_list] declare type sql_cur is ref cursor; my_cur sql_cur; emp_info emp%rowtype; sql_string varchar():=&请输入查询字符串; begin open my_cur for sql_string; loop fetch my_cur into emp_info; exit when my_cur%notfound; dbms_outputput_line(emp_infoename); end loop; close my_cur; end;
游标变量的特点 ()游标变量可以从不同的结果集中提取记录 ()游标变量可以做为存储过程参数进行传递 ()游标变量可以引用游标的所有属性 ()游标变量可以进行赋值运算 使用游标变量也有一定的限制 ()for update 子句不能与游标变量一起使用 ()不允许在程序包使用游标变量(可以声明游标类型) ()另一台服务器上的子过程不能接受游标变量参数 ()不能将NULL值赋给游标变量 ()游标变量不能使用比较运算符 ()数据库中的列不能存储游标变量 总结 ()游标是使用在PL/SQL中是用来查询数据获取结果集的指针 ()游标类型包括隐式游标显示游标和ref游标 ()游标属性包括%found%notfound%rowcount%isopen ()PL/SQL自动定义隐式游标以获取最近执行SQL语句信息 ()循环游标简化处理游标中所有行的查询 ()在声明ref游标时不要将它与select 语句相关联