Oracle 游标

Oracle在运行plsql或者在进行大的sql操作时候需要从表中检索行?那么他是怎么将很多行取出来?

          通过游标一行一行的取出,一行一行的放到内存中。

游标作用:

      指定结果集中特定行的位置。 

      基于当前的结果集位置检索一行或连续的几行。 

      在结果集的当前位置修改行中的数据。 

      可以以编程的方式访问数据库。

游标类型

   隐式游标:在程序中执行dml语句时候,oracle会自动创建名字为sql的隐式游标。

   显式游标:显式游标用于处理返回多行的查询。

   Ref游标(参照游标):ref游标用于处理运行时才能确定的动态sql查询的结果。

 

游标属性:

 %FOUND--sql语句影响了一行或多行时为true

 %NOTDOUND--sql语句没有影响任何行时为true

 %ROWCOUNT--sql语句影响的行数,必须放在一个更新或者删除等修改类语句后面执行,select语句用于查询的话无法使用。

 %ISOPEN--à游标是否打开,始终为false

使用游标属性:

begin  

  update testtable set inc_datetime = sysdate where id = 1;

  if  sql%found  then  dbms_output.put_line('更新了' || sql%rowcount);

  else dbms_output.put_line('更新了' || sql%rowcount);

  end if;

end;

select into 问题:

  在使用显示游标时候经常使用select into 语句,但是在使用select into 时候通常需要进行异常捕获,经常使用的内置异常有 no_data_-found,  too_many_rows。

 

declare

  val varchar2(4000);

begin

   select  t.random_string into val from testtable t where t.id = 10000001;

exception

  when no_data_found then dbms_output.put_line('没有查询到数据');

end;

 

declare

    val varchar2(4000);

begin

    select  t.random_string into val from testtable t; 

exception

  when too_many_rows then dbms_output.put_line('查询数据返回多行');

end;

 

显示游标:

  显式游标在plsql 声明部分定义查询,该查询语句可以返回多行(游标对应查询)

  游标使用步骤--à 声明游标,打开游标,使用游标取出记录,关闭游标。

显式游标(语法定义):

Declare

  cursor 游标名称  is  查询语句

begin

  open 游标名称

    使用游标取出数据

  Close 游标名称

Exception

End;

使用游标取出student中所有的数据:

declare

  --保存 当前行

  rowVal student%rowtype;

  --定义游标

  cursor cursorVal is select * from student;

begin

    open cursorVal;

       loop

         --使用fetch语句把游标里面的值取出,存到变量中

          fetch[A1]  cursorVal into rowVal;

          if

             cursorVal%FOUND

          then

             dbms_output.put_line('姓名' || rowVal.Username  || '性别' ||  rowVal.Sex  || '行数' || cursorVal%rowcount );

          else

            exit;

          end if;

       end loop;

    close cursorVal;

end;

 

带有参数的显示游标:

  语法定义

     Cursor 游标名称(参数名称 参数类型) is 查询语句;

 注意:在定义带有参数游标时不能指定长度,并且在定义带参数游标时一定要在查询语句中使用,否则就失去了意义。

 

使用带参数游标查询数据:  

declare

   rowRes student%rowtype;

         --游标名称(参数名称 参数类型)

   cursor getParCursor(parEmp student.id%type ) is select * from student e where e.id = parEmp;

begin

    --打开游标传递值

    open getParCursor(3);

    loop

      fetch getParCursor into rowRes;

      if

        getParCursor%notfound

      then

        exit;

      else 

        dbms_output.put_line('姓名' || rowRes.Username  || '性别' ||  rowRes.Sex  );

      end if; 

    end loop;

end;

 

使用游标更新获删除数据:

 在使用游标时候可以进行更新或删除数据行,但是声明游标必须使用 select for update语句,然后在更新或删除语句后面加上 where current of 游标名称。

语法定义

 Course 游标名称 is 查询语句 select … for update ;

Update或者 Delete语句 …… where current of 游标名称。

使用游标更新表中记录

declare

   rowRes testtable%rowtype;

   cursor updateCursor is select * from testtable t where t.random_string = 'E983CHQABJ0722KHSWME' for update ;

begin

    open updateCursor;

    loop

      fetch updateCursor into rowRes;

      if

        updateCursor%notfound

      then

        exit;

      else

          if

             rowRes.Random_String = 'E983CHQABJ0722KHSWME'

          then

            update testtable set Random_String = '王五' where current of  updateCursor;

          else

             exit;

          end if;

       end if;

    end loop;

end;

使用游标更新或删除时注意:如果在使用游标进行删除或更新时候,在更新语句后面没有加 where current of 游标名称,那么在更新或删除时影响的行数就是这条语句的结果,如果此条语句在循环里面执行,那么将执行声明部分的游标对应的select语句查询出多少结果集的次数。

循环游标:

  循环游标可以用来简化游标处理代码,在使用循环游标时候不需要打开或者关闭游标,在使用循环游标时不能够进行更新和删除。

语法定义:

   For 变量  in 游标名称

   Loop

     ……

   End loop;

 

使用循环游标输出所有学生信息:

declare

   cursor forCursor is select * from student;

begin

   for cursor_index in  orCursor

     loop

         dbms_output.put_line('姓名' || cursor_index.Username  || '性别' ||  cursor_index.Sex  );

     end loop;

end;

 

REF(动态)游标:

 Ref游标和游标变量用于处理运行时动态执行的sql查询,显式游标是在定义的时候将某个游标对应某个查询,ref在定义时候不能确定,只有在运行时候才能确定对应的哪个sql。   

 语法定义(Ref游标)

declare  

 Type 名称 is ref  cursor-----声明ref游标类型

  游标名称 游标类型-----声明ref游标类型的变量

begin

  Open 游标名称 for select语句----打开游标

End;

 

栗子:对应于每一个学生,求出他的总的选课记录,把每个学生的选课记录插入到student2表中

   创建表语句

create table student (xh number, xm varchar2(10));

insert into student values(1,'A'); 

insert into student values(2,'B');

insert into student values(3,'C');

insert into student values(4,'D');

create table address (xh number, zz varchar2(10));

insert  into address values(2,'郑州');

insert  into address values(1,'开封');

insert  into address values(3,'洛阳');

insert  into address values(4,'新乡');

 

  student2中的结果如下:

                      XH KC

                 --- -------------------------------------------

                       1 语文数学英语历史

                       2 语文数学英语

                       3 语文英语

 

declare

  xhVal student.xh%type; 

  kcVal student.kc%type;

  --定义变量接收学生对应的所有课程

  keValAll varchar2(1000) := '';

  --定义显式游标,指向学生学号

  cursor stuCursor is select  distinct s.xh from student s;

  --定义ref游标

  type refType is ref cursor ;

  refCursor refType;

begin

  open stuCursor;

   loop

     fetch stuCursor into xhVal;

     if

       stuCursor%found

     then

         --打开ref游标

          open refCursor for select s1.kc from student s1 where s1.xh = xhVal;

              keValAll := '';

              loop

                fetch refCursor into kcVal;

                if

                  refCursor%found

                then

                  keValAll := kcVal || keValAll;

                else

                  exit;

                end if;     

              end loop;

           --插入数据到student2

               insert into student2 values (xhVal,keValAll);

          close refCursor;

     else

       exit;

     end if;   

   end loop;

  close stuCursor;

end;

 [A1]FETCH语句一次取一行数据,要返回多行需重复执行,可以使用循环语句来实现。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值