Oracle中游标Cursor的用法详解

 更新时间:2022年05月06日 08:50:29   作者:springsnow  
本文详细讲解了Oracle中游标Cursor的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、使用游标

对于DML语句和单行select into ,oracle自动分配隐形游标。处理select返回多行语句,可以使用显式游标。

使用显示游标处理多行数据,也可使用SELECT..BULK COLLECT INTO 语句处理多行数据.

1.定义游标

cursor cursor_name is select_statement;

2.打开游标

执行对应的SELECT语句并将SELECT语句的结果暂时存放到结果集中.

open cursor_name;

3.提取数据

打开游标后,SELECT语句的结果被临时存放到游标结果集中,使用FETCH语句只能提取一行数据

通过使用FETCH..BULK COLLECT INTO语句每次可以提取多行数据

fetch cursor_name into variable1,varibale2,...;

fetch cursor_name bulk collect into collect1,collect2,...[limit rows];

(1)游标中使用fetch..into语句:只能处理一行数据,除非用循环语句

declare
          v_bookname varchar2(100);
          cursor c_book(i_id number) is select bookname from book where id = i_id;
    begin
        Open c_book(10);--打开游标
        Loop
            Fetch c_book into v_bookname; --提取游标
            exit when c_book%notfound;
            update book set price = '33' where bookname = v_bookname;
        End Loop;
        Close c_book;--关闭游标
    end;

declare
          v_bookname varchar2(100);
          cursor c_book(i_id number) is select bookname from book where id = i_id;
begin
          Open c_book(10);
          Fetch c_book into v_bookname;--预先Fetch一次
          While c_book%found Loop
              update book set price = '33' where bookname = v_bookname;
               Fetch c_book into v_bookname;
          End Loop;
         Close c_book;
end;

(3)基于游标定义记录变量

declare
    cursor emp_cursor is select ename,sal from emp;
    emp_record emp_cursor%rowtype;
  begin
    open emp_cursor;
    loop
     fetch emp_cursor into emp_record;
     exit when emp_cursor%notfound;
     dbms_output.put_line('雇员名:'||emp_record.ename||',雇员工资:'||emp_record.sal);
    end loop;
 end;

4.关闭游标

close cursor_name;

5.游标属性

用于返回显示游标的执行信息,包括%isopen,%found,%notfound,%rowcount

  • %isopen:确定游标是否打开
  • %found:检查是否从结果集中提取到了数据
  • %notfound:与%found行为相反。
  • %rowcount:返回当前行为止已经提取到的实际行数

no_data_found和%notfound的用法是有区别的,小结如下1)SELECT. . . INTO 语句触发 no_data_found;
2)当一个显式光标(静态和动态)的 where 子句未找到时触发 %notfound;
3)当UPDATE或DELETE语句的where 子句未找到时触发 sql%notfound;
4)在光标的提取(Fetch)循环中要用 %notfound 或%found 来确定循环的退出条件,不要用no_data_found。

6.参数游标

注意:定义参数游标时,游标参数只能指定数据类型,而不能指定长度。

declare
    cursor emp_cursor(no number) is select ename from emp where deptno=no;
    v_ename emp.ename%type;
  begin
    open emp_cursor(10);
    loop
     fetch emp_cursor into v_ename;
     exit when emp_cursor%notfound;
     dbms_output.put_line(v_ename);
    end loop;
    close emp_cursor;
  end;

二、for循环遍历,实现遍历游标最高效方式。

使用FOR循环时,ORACLE会隐含的打开游标,提取游标数据并关闭游标。

每循环一次提取一次数据,在提取了所有数据后,自动退出循环并隐含的关闭游标。

1.使用游标FOR循环

--不需要声明v_bookname,Open和Close游标和fetch操作(不用打开游标和关闭游标,实现遍历游标最高效方式)
declare
 cursor c_book(i_id number) is select bookname from book where id = i_id;
begin
   for cur in c_book(10) loop --循环变量cur不需要声明
     update book set price = '53' where bookname = cur.bookname;
   end loop;
end;

2.在游标FOR循环中直接使用子查询

begin
     for emp_record in (select ename,sal from emp) loop
        dbms_output.put_line(emp_record.ename);
    end loop;
end;

三、使用游标更新或删除数据

要通过游标更新或删除数据,在定义游标时必须要带有FOR UPDATE子句

cursor cursor_name(parameter_name datetype) is select_statement for update [of column_reference] [nowait];
  • for update子句:用于在游标结果集数据上家行共享锁,防止其他用户在相应行执行DML操作
  • of子句:确定哪些表要加锁,没有OF子句,则在所引用的全部表上加锁
  • nowait子句:用于指定不等待锁
  • 必须在UPDATE后DELETE语句中引用WHERE CURRENT OF子句
    update table_name set column=.. where current of cursor_name;
    delete table_name where current of cursor_name;
declare
    cursor emp_cursor is select ename,sal from emp for update;
    v_ename emp.ename%type;
    v_sal emp.sal%tyep;
  begin
    open emp_cursor;
    loop
     fetch emp_cursor into v_ename,v_oldsal;
     exit when emp_cursor%notfound;
     if v_oldsal<2000 then
        update emp set sal=sal+100 where current of emp_cursor;--delete from emp where current of emp_cursor;
     end if;
   end loop;
   close emp_cursor;
 end;

四、通过bulk collect减少loop处理的开销

将查询结果一次性加载到集合中,而不是一条一条的加载。

(1)在显示游标中,使用FETCH..BALK COLLECT INTO语句提取所有数据

declare
   cursor emp_cursor is select ename from emp where deptno=10;
    type ename_table_type is table of varchar2(10);
    ename_table ename_table_type;
  begin
    open emp_cursor;
    fetch emp_cursor bulk collect into ename_table;
    for i in 1..ename_table.count loop
       dbms_output.put_line(ename_table(i));
    end loop;
    close emp_cursor;
  end;

(2)游标中使用FETCH..BULK COLLECT INTO ..LIMIT语句提取部分数据

declare
    type name_array_type is varray(5) of varchar2(10);
    name_array name_array_type;
    cursor emp_cursor is select ename from emp;
    rows int:=5;
    v_count int:=0;
  begin
    open emp_cursor;
    loop
     fetch emp_cursor bulk collect into name_array limit rows;
     dbms_output.pur('雇员名');
     for i in 1..(emp_currsor%rowcount-v_count) loop
       dbms_output.put(name_array(i)||' ');
     end loop;
     dbms_output.new_line;
    v_count:=emp_cursor%rowcount;
    exit when emp_cursor%notfound;
    end loop;
    close emp_cursor;
  end;

五、使用游标变量

PL/SQL的游标变量中存放着指向内存地址的指针.

1.游标变量使用步骤

包括定义游标变量,打开游标,提取游标数据,关闭游标等四个阶段

1.1定义ref cursor类型和游标变量

type ref_type_name is ref cursor [return return_type];

cursor_varibale ref_type_name;

当指定RETURN子句时,其数据类型必须是记录类型,不能在包内定义游标变量

1.2打开游标

open cursor_variable for select_statement;

1.3提取游标数据

fetch cursor_varibale into variable1,variable2,...;

fetch cursor_varibale bulk collect into collect1,collect2,...[limit rows]

1.4关闭游标变量

close cursor_varibale;

2.游标变量使用示例

1、在定义FEF CURSOR类型时不指定RETURN子句

在打开游标时可以指定任何的SELECT语句

declare
    type emp_cursor_type is ref cursor;
    emp_cursor emp_cursor_type;
    emp_record emp%rowtype;
  begin
    open emp_cursor for select * from emp where deptno=10;
    loop
     fetch emp_cursor into emp_record;
     exit when emp_cursor%notfound;
     dbms_output.put_line('第'||emp_curosr%rowcount||'个雇员: '||emp_record.ename);
    end loop;
    close emp_cursor;
  end;

2、在定义REF CURSOR类型时指定RETURN子句

在打开游标时SELECT语句的返回结果必须与RETURN子句所指定的记录类型相匹配.

declare
    type emp_record_type is record(name varchar2(10),salary number(6,2));
    type emp_cursor_type is ref cursor return emp_record_type;
    emp_cursor emp_cursor_type;
    emp_record emp_record_type;
  begin
    open emp_cursor for select ename,sal from emp where deptno=20;
    loop
     fetch emp_cursor into emp_record;
     exit when emp_cursor%notfound;
     dbms_output.put_line('第'||emp_curosr%rowcount||'个雇员: '||emp_record.ename);
    end loop;
    close emp_cursor;
 end;

到此这篇关于Oracle中游标Cursor用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Oracle19c安装与基本配置教程(超详细!)

    Oracle19c安装与基本配置教程(超详细!)

    oracle19c数据库安装相对于oracle12c安装还是有些不一样的,所以今天再来记录一下安装过程,下面这篇文章主要给大家介绍了关于Oracle19c安装与基本配置的超详细教程,需要的朋友可以参考下
    2023-01-01
  • Oracle的用户、角色及权限相关操作

    Oracle的用户、角色及权限相关操作

    这篇文章主要介绍了Oracle的用户、角色及权限相关操作,需要的朋友可以参考下
    2017-07-07
  • Oracle中trunc()函数实例详解

    Oracle中trunc()函数实例详解

    trunc函数用法用于截取时间或者数值,返回指定的值,下面这篇文章主要给大家介绍了关于Oracle中trunc()函数详解的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • Oracle表空间与权限的深入讲解

    Oracle表空间与权限的深入讲解

    Oracle表空间(tablespaces)是一个逻辑的概念,真正存放数据的是数据文件(data files),下面这篇文章主要给大家介绍了关于Oracle表空间与权限的相关资料,需要的朋友可以参考下
    2021-11-11
  • Oracle中dblink的实际应用示例详解

    Oracle中dblink的实际应用示例详解

    DBLink的作用是在局域网内,通过一台服务器上面的数据库访问另外一台服务器上面数据库的功能。下面这篇文章主要给大家介绍了关于Oracle中dblink实际应用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友们下面来一起看看吧。
    2017-09-09
  • Oracle显示游标的使用及游标for循环

    Oracle显示游标的使用及游标for循环

    本篇文章给大家介绍oracle显示游标的使用及游标for循环,当查询返回单行记录时使用隐式游标,查询返回多行记录并逐行进行处理时使用显式游标,对本文感兴趣的朋友一起学习吧
    2015-11-11
  • Oracle 随机数

    Oracle 随机数

    用于抽样统计,从数据库中按类别随机 抽取各类用户
    2009-05-05
  • oracle基础语法详解

    oracle基础语法详解

    这篇文章主要介绍了oracle基础语法详解,非常适合Oracle数据库的初步学习,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-05-05
  • 深入Oracle的left join中on和where的区别详解

    深入Oracle的left join中on和where的区别详解

    本篇文章是对Oracle的left join中on和where的区别进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • oracle 日期时间函数使用总结

    oracle 日期时间函数使用总结

    经常写 sql 的同学应该会接触到一些 oracle 的日期时间函数, 例如: 财务软件或者人力资源软件需要按照每年, 每季度, 每月, 甚至每个星期来进行统计
    2014-05-05

最新评论