• oracle数据库笔记1PL/SQL基础3游标


    游标的概念
    
    在ORACLE中, 游标实际上就是在内存中开辟的一个专用SQL区的工作区
    用于存储执行SQL查询命令返回的信息
    
    PL/SQL中有两种类型的光标,显示光标和隐式光标
    
    对于返回多行的查询,为了单个地处理每一行,必须显示地定义一个光标
    
    显示光标的操作
    
    该操作包括定义光标,打开光标,取数据,关闭光标
    
    可用CURSOR OPEN,FETCH和CLOSE控制光标
    
    1.定义游标
    
    在PL/SQL块的说明部分定义游标
    
    定义形式:
    
     CURSOR    游标名称    IS
      
         SELECT    语句;
    
    DECLARE
      cursor c1 is
      select ename,deptno
      from emp
      where sal>2000;
      ...
    BEGIN
      NULL;
    END;
    
    定义游标时可以带参数(形参),给查询传递需要的参数值
    
    游
    标的参数在其查询中,可以在出现常数的地方使用
    
    定义时只要把参数名及其数据类型与游标名称一起说明
    
    传递的参数值可用来在查询中控制查询的结果
    
    带参数的游标定义形式:
    
    CURSOR   游标名(参数[,参数]…) IS 
     
         SELECT  语句;
    
    参数名[IN] 数据类型[{ := | DEFAULT}值]
    
    游标参数的使用范围局限于游标即仅在游标定义中指定的
    
    查询命令内引用。游标参数的值在打开(OPEN)时提供
    
    CURSOR C2(median numbre) IS
      SELECT job,ename
      from emp
      where sal>median;
    
    2. 打开游标
    
    在PL/SQL块中执行语句部分BEGIN之后,使用时要先打开游标 (用OPEN 命令) 。
    
    打开游标的形式:
    
    OPEN    游标名[(实参数)]; 
    
    OPEN  C1 ;
    OPEN  C2 (300);
    
    执行打开游标语句,系统执行游标定义中的查询命令, 标识活
    动集
    
    对带参数的游标,OPEN语句对于游标说明中每一个形式参 数必须有相应的实在参数
    
    若形式参数具有缺省值, 则可不需要有相应的实在参数
    
    游标形参必须是IN参数, 所以不能将值返回给实在参数
    
    在OPEN语句中实在参数与形式参数之间的联系有两种方法
    
    位置表示法:实参与形参个数, 位置一一对应:
    
    OPEN    C2 (300);
    
    命名表示法:以形参=>实参的形式表示:
    
    ey: CURSOR C3(my_name char(10),my_comm number) IS
        SELECT ...
    
    OPEN C3('ATTLEY',300);
    OPEN C3(my_name=>'ATTLEY',my_comm=>300);
    
    3. 利用游标取值
    
    游标被打开后,要用FETCH 语句把查询的记录 取到 PL/SQL
    程序块的变量中
    
    语句形式:
    
    FETCH   游标名  INTO  变量名表;
    
    FETCH语句检索工作区(活动集)中的行,每次只能取一行。
    
    每执行一次FETCH语句, 游标指针下移一行,等待取下一行记录
    
    变量名表中变量的数量和数据类型与查询返回的列的数量与类型相匹配, 位置对应
    
    FETCH C1 INTO my_ename,my_deptno;
    
    注意:
    
    (1) 使用FETCH语句前, 必须先打开游标。
    (2)在FETCH 语句执行过程中, 游标指针只能逐行下移,不能回退。
    
    4. 关闭游标
    
     CLOSE    游标名称
    
    处理完游标工作区中的记录行后, 就以关闭游标了, 游标关闭后,系统释放与该游标相关的所有资源,并使该游标的工作区失效
    
    若此时对游标再执行FETCH语句则出错    但可重新打开游标
    
    对未关闭
    的 游标执行打开也会发生错误
    
    ey:取出部门号为10的雇员姓名和工资
    
    DECLARE 
      v_no emp.deptno%tyoe:=10;
      v_sal emp.sal%type;
      v_ename emp.ename%type;
      n number(3);
      CURSOR C1 IS 
      select ename,sal from emp
      where deptno=v_no;
    BEGIN
      select count(*) into n from emp
      where deptno=v_no;
      open c1;
      for i in 1..n loop
        fetch ci into v_ename,v_sal;
        dbms_output.put_line(v_ename || to_char(v_sal));
      end loop;
      close c1;
    end;
    
    
    declare
     
           my_sal   emp.sal%TYPE;
    
           my_job   emp.job%TYPE;  
           factor    integer:=2;
           cursor  c1  is
        
           select  factor *sal     from  emp
     
           where  job=my_job;
       
    begin
     
            …
           
            my_job :=’MANAGER’;
           
            open  c1;
             
            loop  
          
            fetch  c1  into  my_sal;
            
            exit   when  c1%NOTFOUND;
     
              …
           
            factor:=factor+1; 
            end loop;
                 
            close  c1;
      
    end;
    
    
    游标的属性:
    
    每一个显示定义的游标有四种属性
    
    %NOTFOUND  ,  %FOUND
     
    %ROWCOUNT,  %ISOPEN
    
    利用游标属性可存取有关多行查询执行的信
    
    注意仅在过程性语句中可使用游标属性息
    
    而在SQL语句中不能使用
    
    (1) %NOTFOUND 属性
    
    布尔型属性,若最后FETCH语句执行,没有返回行,则值为
     TRUE
    
    (2) %FOUND 属性
    
    
    布尔型属性,如果最后一个FETCH语句执行时返回行,
     %FOUND为TRUE
    
    在第一个FETCH语句执行前,%FOUND计算得到为NULL值
    
    (3) %ISOPEN属性
    
    
    布尔型属性,当一个游标是打开时,该属性值为TRUE,否则
     为FALSE
    
    对游标工作区检索记录必须先打开游标,否则导致系统错
     误。可用该属性判断游标是否已打开
    
    (4) %ROWCOUNT
    
    
    数字型属性,返回当前已从游标工作区中读取的记录数
    
    该属性返回游标打开后,至今由FETCH语句已获取的行数
    
    在刚打开游标时,该属性值为0,所以第一个FETCH语句执行之前,%ROWCOUND返回 0。
    
    ey:
    
    loop
     fetch c1 into my_ename,my_deptno;
     if c1%rowcount>10 then
       ...
     end if;
    end loop;
    
    在一个PL/SQL块中,可打开多个游标
    
    1: 在数据库表data_table中,存放有实验数据,现对实验的数据进行处理, 将计算结果存入库表temp中。
    
    declare
    
           num1   data_table.n1%type;
    
           num2   date_table.n2%type;
    
           num3   data_table.n3%type;
    
           result   temp.col1%type;
    
           cursor  c1  is
     
             select  n1,n2,n3   from  data_table
     
             where  exper_num=1;
    begin
    
           open  c1;
     
          loop 
     
             fetch  c1  into  num1,num2,num3;
     
            exit  when  c1%NOTFOUND;
    
             result:=num2/(num1+num3);
    
             insert  into  temp   values (result,null,null);
     
            end loop;
      
          close  c1;
    
            commit;
     
    end; 
    
    2: 查询10号部门雇员工资,当查询到第一个工资大于$2000的
      雇员时停止,并按工资少于$2000的雇员人数在TMP表中生成 相同个数的雇员号 
    
    
    DECLARE
     v_deptno emp.deptno%type:=10;
     v_sal emp.sal%type;
     cursor c1 is 
      select sal from emp
      where deptno=v_deptno;
      order by sal ASC;
    BEGIN
      open c1;
      loop
        fetch c1 into v_sal
        exit when v_sal>=2000;
      end loop;
      for i in 1..c1%rowcount loop
         insert into tmp(deptno,empnp)
         values(10,8000+i*100);
      end loop;
      close c1;
      commit work;
    END;
    
    3: 查询10号部门所有雇员姓名、工资,并插入到一个临时表 
     TMP 中
    
    DECLARE 
      v_deptno emp.deptno%type:=10;
      cursor c1 is 
        select ename,sal from emp
        where deptno=v_deptno;
      emp_rec c1%rowtype;
    BEGIN
      open c1;
      fetch c1 into emp_rec;
      while c1%found loop
         insert into tmp(ename,sal)
         values(emp_rec.ename,emp_rec.sal);
         fetch c1 into emp_rec;
      end loop;
      close c1;
      commit work;
    END;
    
    sql>select * from tmp;
    
    隐式光标
    
    ORACLE在处理每一个不与显示说明光标相关的SQL  
      语句时,隐式地打开一光标
    
    PL/SQL可以以“SQL“引用最近的隐式光标
    
    在程序中不能用OPEN,FETCH,CLOSE控制隐式光标
    
    但可利用光标属性存取最近执行的SQL语句的有关信息
    
    SQL光标与显示光标有相同的四种属性
    
    SQL光标属性值总是涉及最后执行的SQL语句
    
    这些语句
    包括有insert, update, delete和 select  into语句
    
    隐式光标四种属性类似显示光标属性, 但不同之处是:
    
    %ROWCOUNT属性返回由 insert, update或 delete所影响的行数以及由select  into所选择的行数。
    
    注意:
    
    select  into返回的行数不能多于一行,如果多于一行,将引
    起预定义例外too_many_rows。
    
    %ISOPEN属性:
    
    oracle在执行每一个相关的SQL语句后, 自动地关闭SQL
    光标, 所以SQL光标的%isopen 属性总是FALSE。
    
    三、游标中FOR循环的使用
    
    当使用游标FOR循环时,系统隐式地说明它的循环控制
    变量为一个记录变量,
    
    执行FOR语句时系统自动打开游标,重复地从游标工作区中读取记录行放置到记录变量的字
     段中
    
    在所有记录行处理完成或被中断退出循环时,自动关闭游标
    
    游标FOR循环语法形式:
    
     FOR    循环计数器    IN    游标名  LOOP
    
       .........
     END LOOP;
    
    
    
    declare
     
              result  temp.col1%type;
    
              cursor  c1  is
     
               select  n1,n2,n3
     
               from  data_table
     
               where  exper_num=1;
          
    begin
    
              for  c1rec   IN  C1  loop
      
                result:=c1rec.n2/(c1rec.n1+c1rec.n3);
    
                  insert  into  temp
     
                 values  (result,null,null);
      
               end loop;
    
               commit;
          
    end;
    
    
    其中,c1rec为系统隐式说明为一记录型变量
    
    等价于  c1rec    c1%ROWTYPE
    
    
    它的各字段可存储由游标c1所获取的全部列值
    
    该记录变量
     仅定义在循环内部,循环体中的语句序列是对满足游标查询的
     每一行执行一次
    
    declare
      v_dno dept.deptno%type:=10;
      cursor c1 is
        select ename,sal from emp
        where deptno=v_dno;
      emp_rec c1%rowtype;
    begin
      for emp_rec in c1 loop;
      insert into tmp(ename,sal)
      values(emp_rec.ename,emp_rec.sal);
      end loop;
      commit work;
    end;
    
    declare
      cursor c1 is 
      select * from emp
      where rownum<=10
      order by ename;
    begin
      for crec in c1 loop
        dbms_output.put_line(crec.ename);
      end loop;
    end;
    
    若不用游标FOR循环,PL/SQL代码
           
    declare
             
     cursor  c1  is
     select  *   from  emp
    
     where   ROWNUM<=10
             
       order  by  ename;
              
      v_rec  emp%rowtype;
          
    begin
         
         open  c1;
     
         fetch  c1  into  v_rec;
    
         while   c1%found  loop
      
            dbms_output.put_line(
    to_ char(c1%rowcount)||‘ ’||v_rec.ename);
    
            fetch  c1  into v_rec.ename;
         end loop;
    
         close c1;
        
    end;     
    
    若用带参数的游标,PL/SQL程序块代码
            
    
    declare
     
      cursor  c1(pattern  varchar2) is
     
      select  *  from  emp
     
      where   ename  like  pattern ||’%’ and  rownunt<=10
    
      order  by  ename;
          
    begin
     
       for  crec  in  c1(‘MAR’) loop
       dbms_output.put_line (crec.ename);
       end loop;
         
    end; 
    
    
    游标使用户可以在PL/SQL程序块中先执行一个查询,然后检索查询所得的记录
    
    在程序块的说明部分定义游标并提供要执行的查询
    
    在程序块的执行部分,需先打开游标,接着读取记录,最后关闭游标
    
    用游标FOR循环处理一个游标工作区记录时,可以把打开游标的过程和读取记录的过程合并在一起
    
    带参数游标提供了更大的灵活性并提高了游标在类似查 询中的重用率
    
    当一个查询返回多条记录时必需使用显示游标
    
    只要有可能,请在代码中使用带参数的游标,这样可重用这些游标,会降低必要的开支量。
    
    四.游标的where current of子句
    
    如果需要对游标选择的行或者列进行更新或者删除,则游标定义语句中必须使用for update 选项
    
    
    其作用为:
    
    迫使Oracle锁定游标结果集的行,防止其他事务处理更新或 删除相同的行,直到当前事务提交或回滚为止
    
    语法格式:
    
    Select ….from ….for update [of column[,column]…..][nowait]
    
    如果在游标中使用了for update 子句,则在delete 和update 语句中可以使用where current of<cursor_name>子句
    以修改或删除游标结果集当前行所对应的表中数据。
    
    
    带有 for update 子句的游标
    
    declare
          cursor sal_cursor is 
          select sal from emp where deptno=30
           for update of sal nowait;
    begin
          for emp_record in sal_cursor loop
           update emp set sal=emp_record.sal*1.1
           where current of sal_cursor;
          end loop;
    end;
    
    五.游标变量(REF CURSOR)
    
    
    1.游标变量是动态的,它不与任何特定的查询绑定在一起。
    
    2.可以为任意兼容的查询打开游标变量,从而提高更好的灵活性。
    
    创建游标变量(REF CURSOR)的步骤
    
    1.定义Ref cursor类型,即引用游标类型
    2.声明这种游标类型的变量。
    
    强类型游标   (有返回值类型)
    TYPE DEPT_CUR IS REF CURSOR
    RUTURN dept%ROWTYPE;
    cur1 DEPT_CUR;
    
    open cur1 for 
    select * from dept where deptno=20;
    
    弱类型游标   (没有返回类型)
    TYPE MYCUR IS REF CURSOR;
    
    游标和游标变量的异同:
    
    游标是数据库中一个命名的工作区,当游标被声明后,他就与一个固定的SQL想关联,
    
    在编译时刻是已知的,是静态的.它永远指向一个相同的查询工作区.
    
    游标变量可以在运行时刻与不同的SQL语句关联,在运行时可以取不同的SQL语句.
    
    它可以引用不同的工作区.
    

      

  • 相关阅读:
    elk2
    elk
    skywalking学习ppt
    Spring Boot]SpringBoot四大神器之Actuator
    黑马程序员spring data jpa 2019年第一版本
    css总结7:盒子模型理解
    css总结5:px、em、rem区别介绍
    css总结4:input 去掉外边框,placeholder的字体颜色、字号
    css总结3:Flex 布局教程:Flex-demos(转)
    css总结2:Flex 布局教程:Flex 语法(转)
  • 原文地址:https://www.cnblogs.com/wust221/p/3069117.html
Copyright © 2020-2023  润新知