• (七)Oracle学习笔记—— 游标


    1.游标简介

      游标用来处理从数据库中检索的多行记录(使用SELECT语句)。利用游标,程序可以逐个地处理和遍历一次检索返回的整个记录集。

      为了处理SQL语句,Oracle将在内存中分配一个区域,这就是上下文区。这个区包含了已经处理完的行数、指向被分析语句的指针,整个区是查询(select)语句返回的数据行集。游标就是指向上下文区句柄或指针。

    2.游标使用

      2.1 定义一个游标

    CURSOR cursor_name IS select_statement;

    例如:把数据表中emp中部门号为20的员工定义为游标:

    CURSOR exce_emp is select * from scott.emp where deptno=20;

    注意:在声明游标时,select_statement不能包含INTO子句。当使用显示游标时,INTO子句是FETCH语句的一部分。

      2.2 为查询打开游标

      打开游标实际上是从数据表中读取数据的过程,在这个过程中主要完成两件事:

                 ①把select查询结果读入内存工作区中。

                 ②将游标指针定位在第一条记录。

    OPEN cursor_name

      2.3 取得结果放入PL/SQL变量中(利用fetch命令从游标中提取数据)

       FETCH命令首先将当前游标指针所指的行读出来并且置于相应的变量中,然后把游标指针移到下一行。所以FETCH命令每一个执行的时候,只能提取一行或者部分的数据。

    FETCH cursor_name INTO list_of_variables;  --变量(变量名1,变量名2......)
    FETCH cursor_name INTO PL/SQL_record;    --记录型变量名

      2.4 关闭游标

    CLOSE cursor_name

    举例:

    declare
       cursor exce_emp is select * from emp where empno=6676;            --定义游标
       var_exce_emp exce_emp%rowtype;          --定义变量
    begin
      open exce_emp;         --打开游标
      fetch exce_emp into var_exce_emp;            --fetch提取数据
      dbms_output.put_line('提取的数据为:员工的姓名:'||var_exce_emp.ename||',员工的工作为:'||var_exce_emp.job);
      close exce_emp;
    end;

    3.游标的属性

    针对2.3,如果游标指针已经指到了游标的末尾,那么FETCH命令将读不到数据了,所以有这样一种机制,这种机制可以测出游标是否已经指到了游标的末尾。这种机制就是游标的属性。

    游标有四个属性:%FOUND、%ISOPEN、%NOTFOUND、%ROWCOUNT

      3.1 %FOUND

    该属性用于测试在自己所在语句之前的最后一个FETCH命令是否提取到了数据。如果能够提取到数据就返回true,否则返回false。但是如果一个游标还没有被打开就运用%FOUND,那么将会产生INVALID_CURSOR异常。

    declare
       cursor exce_emp is select empno,ename from emp where deptno=20;
       var_exce_emp exce_emp%rowtype;
       i int := 1;
    begin
      open exce_emp;
      loop
        fetch exce_emp into var_exce_emp;
        if exce_emp %found then        --利用%found属性检测是否提取到了数据
          dbms_output.put_line(''||to_char(i)||'个员工的信息-------编号:'||var_exce_emp.empno||'员工姓名:'||var_exce_emp.ename);
          i := i+1;
        else
          exit;
        end if;
      end loop;
      close exce_emp;
    end;

      3.2 %ISOPEN

    该属性主要用于测试游标是否已经打开。

    declare
       cursor exce_emp is select empno,ename from emp;
       var_exce_emp exce_emp%rowtype;
    begin
      if not exce_emp%isopen then        --检测游标是否已经打开
        dbms_output.put_line('游标没有打开');
        open exce_emp;
      else
        dbms_output.put_line('游标已经打开了');
      end if;
    end;

      3.3 %NOTFOUND 

    fetch是否提到数据 没有true 提到false。

      3.4 %ROWCOUNT

    已经取出的记录的条数

    当刚刚打开游标时,%ROWCOUNT的值为0。每运行一次FETCH命令,%ROWCOUNT的值就会自增1。因此%ROWCOUNT的值可以看着是游标中当前被读取了的记录的条数,即游标循环中处理的当前行数。如果一个有游标在打开之前调用%ROWCOUNT属性,就会产生异常INVALID_CURSOR。

    declare
      cursor exce_emp is empno,ename from emp where deptno=20;
      var_exce_emp exce_emp%rowtype;
      n int := 5;
    begin
      open exce_emp;
      loop
        fetch exce_emp into var_exce_emp;
        exit when exce_emp%notfound;
        dbms_output.put_line('员工号:'||var_exce_emp.empno||',员工姓名:'||var_exce_emp.ename);
        exit when exce_emp%rowcount=n;
      end loop;
      close exce_emp;
    end;

    4.隐式游标

    【2.游标使用】介绍的都是显式游标。Oracle还默认了一种游标,这个游标就是隐式游标,隐式游标是不需要打开和关闭的。其被定义为SQL。它同时也具有4个属性。

    declare
      tempdeptno := 20;
      counts int := 0;
    begin
      update emp set job='CLERK' where deptno = tempdeptno;
      if sql%found then
        counts := sql%rowcount;
      end if;
      dbms_output.put_line(''||to_char(counts)||'行语句做了修改');
    end;

    显式游标和隐式游标的区别:         

            

    5.游标的常见操作

      5.1 FOR循环游标 (常用的一种游标)

    --<1>定义游标
     --<2>定义游标变量
     --<3>使用for循环来使用这个游标
    
      --前向游标 只能往一个方向走
      --效率很高
          declare
            --类型定义
            cursor cc is select empno,ename,job,sal
             from emp where job = 'MANAGER';
            --定义一个游标变量
            ccrec cc%rowtype;
          begin
             --for循环
             for ccrec in cc loop
                dbms_output.put_line(ccrec.empno||'-'||ccrec.ename||'-'||ccrec.job||'-'||ccrec.sal);
             end loop;       
          end;

      5.2 FETCH游标

     --使用的时候 必须要明确的打开和关闭
          declare
            --类型定义
            cursor cc is select empno,ename,job,sal
             from emp where job = 'MANAGER';
            --定义一个游标变量
            ccrec cc%rowtype;
          begin
            --打开游标
             open cc;
            --loop循环
             loop
                --提取一行数据到ccrec中 
                fetch cc into ccrec;         
                --判断是否提取到值,没取到值就退出
                --取到值cc%notfound 是false
                --取不到值cc%notfound 是true 
                exit when cc%notfound;
                dbms_output.put_line(ccrec.empno||'-'||ccrec.ename||'-'||ccrec.job||'-'||ccrec.sal);            
             end loop; 
            --关闭游标
             close cc;  
          end;

      5.3 参数游标

    --按部门编号的顺序输出部门经理的名字
         declare
           --部门
           cursor c1 is select deptno from dept;
           --参数游标c2,定义参数的时候
           --只能指定类型,不能指定长度  
           --参数只能出现在select语句=号的右侧
           cursor c2(no number,pjob varchar2) is select emp.* from emp
             where deptno = no and job=pjob;
           c1rec c1%rowtype;
           c2rec c2%rowtype;
           --定义变量的时候要指定长度
           v_job varchar2(20);
         begin
           --部门
            for c1rec in c1 loop
              --参数在游标中使用
              for c2rec in c2(c1rec.deptno,'MANAGER') loop
                dbms_output.put_line(c1rec.deptno||'-'||c2rec.ename);
              end loop; 
            end loop; 
         end; 

      5.4 引用游标 / 动态游标

    -- select语句是动态的
         declare
           --定义一个类型(ref cursor)弱类型    
           type cur is ref cursor;
             --强类型(返回的结果集有要求)
           type cur1 is ref cursor return emp%rowtype;
           --定义一个ref cursor类型的变量   
           cura cur;
           c1rec emp%rowtype;
           c2rec dept%rowtype;
         begin
      DBMS_output.put_line('输出员工')   ;       
           open cura for select * from emp;
           loop
             fetch cura into c1rec;   
             exit when cura%notfound;
             DBMS_output.put_line(c1rec.ename)   ;
           end loop ;
      DBMS_output.put_line('输出部门')   ;
           open cura for select * from dept;
           loop
             fetch cura into c2rec;   
             exit when cura%notfound;
             DBMS_output.put_line(c2rec.dname)   ;
           end loop;  
           close cura;
        end;
  • 相关阅读:
    PowerGhost
    watchdogs感染性挖矿病毒
    XorDDoS木马
    Gates(盖茨)木马
    seasame病毒
    zabbix监控之邮件报警通知
    ubuntu18.04 heirloom-mailx 通过外部SMTP服务器发送邮件
    linux小常识
    zabbix基本概念
    Zabbix图表中文乱码
  • 原文地址:https://www.cnblogs.com/zjfjava/p/7469497.html
Copyright © 2020-2023  润新知