0
点赞
收藏
分享

微信扫一扫

EHS管理系统设备安全设施安全监控模块

无奋斗不青春

分隔线
在这里插入图片描述

PL-SQL进阶—游标

游标

作用

  • 在pl/sql编程中,我们通常处理多行事务是通过游标来实现的(这个可以类比java中迭代器概念)
  • 游标是一个指向上下文的句柄和指针,通过游标pl/sql可以控制上下文区和处理语句时上下文会发生一些事情。
  • 对于不同的sql语句游标的使用情况又是不同的,如下:
    • 对于非查询语句 : 游标是隐式的;
    • 对于结果为单行的查询语句:游标是隐式的或显示的;
    • 对于结果为多行的查询语句:游标是显示

显式游标

  • 第一步:定义游标

    CURSOR cursor_name [(param1,parame2..)] IS SELECT. 
    //后面接的是一个查询语句,一般都是返回多行的那种。
    其中参数param可带可不带,根据需要,参数的定义也要定义参数名,参数类型等(这里特别要主要的是在指定参数类型的时候不需要指定类型大小 如number(20),这都是错的)
    
  • 第二步:打开游标

    OPEN cursor_name [value,value2…]
    
    //pl/sql中不能使用open重复打开同一个游标 
    
  • 第三步:提取数据 就是检索结果集中的数据行,放入到指定的输出变量

    fetch cursor_name into {variable_list | record_variable };
    
    • 对该记录进行处理,
    • 继续处理,直到结果集中没有记录
  • 第四步:关闭游标 ,释放游标所占有的资源,同时使该工作区变为无效,不能再使用fetch提取数据,可以使用open重新打开。

    close cursor_name;
    
  • 示例

  • 下面就通过一些实例来看看游标到底怎么用的吧。

  • 如:查询员工表前十名的员工的信息

    declare 
        v_sal employees.salary%type; 
        v_name employee.last_name%type; 
        cursor empcursor is select last_name,salary from employees where rownum <11 order by desc; 
    begin 
        –打开游标 
        open empcursor ; 
        –提取数据; 
        fetch empcursor into v_name,v_sal ; 
        while empcursor%found loop 
        dbms_output.put_line(v_name||,||v_sal); 
        fetch empcursor into v_name,sal; 
        end loop; 
        close empcursor; 
    end;
    
  • 在演示一下带参数的(rownum根据参数确定)

    declare 
        v_sal employees.salary%type; 
        v_name employee.last_name%type; 
        
        cursor empcursor(empno number default 11) is select last_name,salary from employees where rownum
    


游标概念及意义

  • 1、游标概念:游标本质是一块内存区域,由系统或用户以变量的形式定义,可以提高数据库数据处理速度。游标的工作机制是一种能从包括多行数据记录的结果集中每次提取一行记录的机制,即游标提供了在逐行的基础上操作表中数据的方法。
  • 注意:类似于java中迭代器(iterator)
  • 2、解决问题:数据库在并没有一种描述表中单一记录的表达形式,除非使用where 子句来限制只有一条记录被选中。因此我们必须借助于游标来进行面向单条记录的数据处理。在PL/SQL程序中,对于处理多行记录的事务经常使用游标来实现。

游标的类型

  • 1、隐式游标:在 PL/SQL 程序中执行DML SQL 语句时自动创建隐式游标;
  • 2、显式游标:显式游标用于处理返回多行的查询;
  • 3、REF 游标:REF 游标用于处理运行时才能确定的动态 SQL 查询的结果;
隐式游标
  • 1、隐式游标概念:在PL/SQL中使用DML语句时自动创建隐式游标,隐式游标自动声明、打开和关闭,其名为 SQL,通过检查隐式游标的属性可以获得最近执行的 DML 语句的信息;
  • 2、隐式游标的属性:
    • (1)%FOUND:SQL 语句影响了一行或多行时为 TRUE;
    • (2)%NOTFOUND:SQL 语句没有影响任何行时为TRUE;
    • (3)%ROWCOUNT:SQL 语句影响的行数;
    • (4)%ISOPEN:游标是否打开,始终为false。
  • 注意:忽略大小写即大小写都可以。
显示游标
  • (一)显示游标处理需要四个PL/SQL步骤:
  • 1、定义(声明)游标:定义一个游标名以及与其对应的select语句。
    • 语法:
      cursor cursor_name[(parameter[,parameter])] 
          [return datatype]
      is
          select_statement;
      
    • 参数说明:
      • 游标参数只能为输入参数
      • 格式如下:
        parameter_name [IN] datatype
        
      • 注意:in关键字可以省略,在指定数据类型时,不能使用长度约束。
      • 如:NUMBER(4),CHAR(10)等都是错误的
    • 返回值
      • [return datatype]是可选的,表示游标返回数据的数据类型
      • 如果选择有,则应该严格与select_statement中的选择列表在数据次序和数据类型上匹配一致
      • 注意:数据类型一般是记录数据类型或带“表名或者游标名%ROWTYPE”的数据类型。
  • 2、 打开游标
    • 就是执行游标所对应的SELECT语句,将其查询结果放入工作区,并且指针指向工作区的首部,标识游标结果集合
    • 注意:如果游标查询语句中带有for update选项,open语句还将锁定数据库表中游标结果集合对应的数据行
    • 语法:
      open cursor_name[value1,value2,...];
      
      • 注意:PL/SQL程序不能用OPEN语句重复打开一个游标。
  • 3、提取游标数据
    • 就是检索结果集合中的数据行,放入指定的输出变量中
    • 语法:
      fetch cursor_name into {variable_list|record_variable};
      
      • 注意:variable_list表示table属性定义的数组,数据类型需指定和数据库表中某个字段类型一致
    • 语法:
      type 变量名词 is table of emp.ename%type index by binary_integer;
      
      • 注意:record_variable表示表名或者游标名%rowtype属性用于定义record变量,类似定义一个类,该类可以直接调用数据库表中所有字段。
    • fetch语句执行过程
      • 执行FETCH语句时,每次返回一个数据行,然后自动将游标移动指向下一个数据行
      • 当检索到最后一行数据时,如果再次执行FETCH语句,将操作失败,并将游标属性%NOTFOUND置为TRUE
      • 所以每次执行完FETCH语句后,检查游标属性%NOTFOUND就可以判断FETCH语句是否执行成功并返回一个数据行,以便确定是否给对应的变量赋了值。继续处理,直到活动集合中没有记录;
  • 4、关闭游标
    • 当提取和处理完游标结果集合数据后,应及时关闭游标,以释放该游标所占用的系统资源,并使该游标的工作区变成无效,不能再使用FETCH语句取其中数据。
    • 注意:关闭后的游标可以使用OPEN语句重新打开。
    • 语法:
      close cursor_name;
      
游标实例
  • 实例1
    declare
        cursor c is select * from emp;
        demo c%rowtype;
    begin
        open c;
        fetch c into demo;
        dbms_output.put_line(demo.ename);
        close c;
    end;
    
  • 实例2
    declare
        cursor c is select * from emp;
        v_emp c%rowtype;
    begin
        open c;
        loop
            fetch c into v_emp;
            exit when (c%notfound);
            dbms_output.put_line(v_emp.ename);
        end loop;
        close c;
    end;
    
  • 实例3
    declare
        cursor c is select * from emp;
        v_emp c%rowtype;
    begin
        open c;
        fetch c into v_emp;
        while (c%found) loop
            dbms_output.put_line(v_emp.ename);
            fetch c into v_emp;
        end loop;
        close c;
    end;
    
  • 使用游标建议使用for循环(因为for循环不用fetch,)
    declare
        cursor c is select * from emp;
    begin
        for v_emp in c loop
            dbms_output.put_line(v_emp.ename);
        end loop;
    end;
    
带参数的游标
  • 实例
    declare
        cursor c (v_deptno emp.deptno%type, v_job emp.job%type) is select ename, sal from emp where deptno = v_deptno and job = v_job;
    begin
        for v_temp in c(30,'CLERK') loop
            dbms_output.put_line(v_temp.ename);
        end loop;
    end;
    
可更新的游标
  • 实例
    declare
        cursor c is select * from emp2 for update;
    begin
        for v_temp in c loop
            if (v_temp.sal < 2000) then
                update emp2 set sal = sal * 2 where current of c;
            elsif (v_temp.sal = 5000) then
                delete from emp2 where current of c;
            end if;
         end loop;
         commit;
    end;
    
For 循环游标
  • 定义游标
  • 定义游标变量
  • 使用for循环来使用这个游标
    declare
       --类型定义
       cursor c_job is select empno,ename,job,sal from emp where job='MANAGER';
       
       --定义一个游标变量v_cinfo c_emp%ROWTYPE ,该类型为游标c_emp中的一行数据类型
       c_row c_job%rowtype;
    begin
        for c_row in c_job loop
            dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
        end loop;
    end;
    
Fetch游标
  • 使用的时候必须要明确的打开和关闭
    declare 
        --类型定义
        cursor c_job is select empno,ename,job,sal from emp where job='MANAGER';
        
        --定义一个游标变量
        c_row c_job%rowtype;
    begin
        -- 打开游标
        open c_job;
        
        -- 循环
        loop
            --提取一行数据到c_row
            fetch c_job into c_row;
            
            --判断是否提取到值,没取到值就退出
            exit when c_job%notfound;   -- 当c_job没有查找到数据notfound,则退出exit
                dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
        end loop;
        
        --关闭游标
        close c_job;
    end;
    
举报

相关推荐

0 条评论