PLSQL基础(三)游标

游标有两种:

显示游标,隐式游标

 

显示游标是用CURSOR...IS命令定义的游标,它可以对查询语句(SELECT)返回的多条记录进行处理,而隐式游标是在执行插入(INSERT),删除(DELETE),修改(UPDATE)和返回单条记录的查询(SELECT)语句时由PLSQL自动定义的。

 

显示游标的操作

1)打开游标    2)推进游标     3)关闭游标

 

 

声明游标:

DECLARE

    v_auths auths%ROWTYPE;

    v_code auths.author_code%TYPE;

    CURSOR c_auths IS

     SELECT * FROM auths WHERE author_code = v_code;

 

打开游标:

v_code = 'A00001';

OPEN c_auths;

 

声明游标

DECLARE

    CURSOR c_Auths(P_code auths.author_code%TYPE) IS

    SELECT * FROM auths WHERE author_code = P_code;

打开游标

OPEN c_Auths('A00001');

 

当打开显示游标后,就可以使用FETCH语句来推进游标,返回查询结果中的一行。没执行完一条FETCH语句后,显示游标会自动指向查询结果集的下一行。

FETCH c_Auths INTO c_Auths;

 

当整个结果集都检索完以后,应当关闭游标,关闭游标用来通知PLSQL游标操作已经结束,并且释放游标所占用的资源.

CLOSE cursor_name;

 

 

游标的属性

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

 

显式游标的推荐循环

DECLARE

    v_Salary  Auths.salary%TYPE;

    v_Code    Auths.author_code%TYPE;

    CURSOR c_salary IS

    SELECT salary,author_code FROM auths WHERE author_code <= 'A00006';

BEGIN

     OPEN c_salary;

    LOOP

         FETCH c_salary INTO v_Salary,v_Code;

         EXIT WHEN c_salary%NOTFOUNT;

         IF v_salary <= 2000 THEN

              UPDATE auths SET salary = salary + 50 WHERE author_code = v_Code;

         END IF;

     END LOOP;

 

     CLOSE c_salary;

   COMMIT;

END;

 

无论是使用LOOP...END LOOP语句还是使用WHILE...LOOP语句来完成游标的推进循环,都必须使用OPEN,FETCH,CLOSE语句来控制游标的打开,推进和关闭,PLSQL还提供了一种简单类型的循环,可以自动控制游标的打开,推进和关闭,这叫做游标的FOR循环.

DECLARE

    CURSOR c_salary IS

    SELECT salary FROM auths WHERE author_code <= 'A00006';

BEGIN

--开始游标FOR循环,隐含地打开c_salary游标

    FOR v_salary IN c_calary LOOP

          IF v_salary.salary <= 200 THEN

               UPDATE auths SET salary = salary + 50 WHERE salary = v_salary.salary;

          END IF;

    END LOOP;

    COMMIT;

END;

 

上例中v_salary没有在块的定义部分声明,该变量被PLSQL编译器隐含的声明了,该变量的类型为c_salary%ROWTYPE,其作用域只在循环内部。

 

 

 

隐式游标

显示游标仅仅是用来控制返回多行的SELECT语句,而隐式游标是指向处理所有的SQL语句的环境区域的指针,隐式游标也叫SQL游标,与显示游标不同的是,SQL游标不能通过专门的命令打开或关闭,PLSQL隐式的打开SQL游标,并在它内部处理SQL语句,然后关闭它。

SQL游标用来处理INSERT,UPDATE,DELETE以及返回一行的SELECT ...INTO语句。一个SQL游标不管是打开还是关闭,OPEN,FETCH,CLOSE命令都不能操作它。

SQL游标与显示游标类似,也有%FOUND,%NOTFOUND,%ISOPEN,%ROWTYPE属性,SQL游标的属性通常是返回执行INSERT,DELETE,UPDATE或SELECT...INTO语句时的信息,当打开SQL游标之前,SQL游标的属性都是NULL.

%FOUND

当使用INSERT,DELETE或者UPDATE语句处理一行或多行,或执行SELECT INTO语句返回一行时,%FOUND属性返回TRUE,否则返回FALSE.

注意:如果执行SELECT INTO语句时返回多行,则会产生TOO_MANEY_ROWS异常,并将控制权转移到异常处理部分,%FOUND属性并不返回TRUE.如果执行SELECT INTO语句时返回0行,会产生NO_DATE_FOUND异常,%FOUND属性并不返回FALSE.

 

%NOTFOUND

%NOTFOUND恰与%FOUND属性相反,当使用INSERT,DELETE或者UPDATE语句处理的函数为0时,%NOTFOUND属性返回TRUE,否则返回FALSE.

 

%ISOPEN

因为在执行了DML语句后,Oracle会自动关闭SQL游标,所以%ISOPEN总会FALSE.

 

%ROWCOUNT

该属性返回执行INSERT,DELETE或UPDATE语句返回的行数,或返回执行SELECT INTO语句时查询的行数,如果INSERT,DELETE,UPDATE或SELECT INTO语句返回的行数为0,则%ROWTYPE属性返回0.

BEGIN  

      UPDATE auths SET entry_date_time = SYSDATE WHERE author_code = 'A00007';

     --如果UPDATE语句中修改的行不存在(SQL%NOTFOUND返回TURE)

 IF SQL%NOTFOUND THEN

      INSERT INTO auths values(......)......

END IF;

END;

我们使用SQL%ROWCOUNT完成与上例相同的功能。

BEGIN

    UPDATE auths SET entry_date_time = SYSDATE WHERE author_code = 'A00007';

     IF SQL%ROWCOUNT = 0 THEN

         INSERT INTO ......

    END IF;

END;

 

 

 

游标变量

到目前为止前面所有显示游标的例子都是静态游标----即游标与一个SQL语句关联,并且该SQL语句在编译时已经确定,而游标变量是一个引用类型(REF)的变量,当程序运行时使用游标变量可以指定不同的查询,所以游标变量的使用比静态游标更灵活。

我们可以使用一个没有指定结果集类型的游标变量来指定多个不同类型的查询.

DECLARE

--定义游标变量类型t_CurRef,该变量类型没有指定结果集类型,所以该游标变量类型的变量可以返回不同的PLSQL记录类型

        TYPE t_CurRef IS REF COUSOR

--声明一个游标变量类型的变量

          c_CursorRef t_CurRef;

--定义PLSQL记录类型

         TPYE t_AuthorRec IS RECORD

        (

                AuthorCode auths.author_code%TYPE;

                Name auths.name%TYPE

        );

       

        TYPE t_ArticleRec IS RECODE

         (

                 AuthorCode article.author_code%TYPE

                 Title     article.Title%TYPE

           );

  --声明两个记录类型变量

   v_Author t_AuthorRec;

   v_Ariticle  t_ArticleRec;

BEGIN

--打开游标变量c_CursorRef,返回t_AuthorRec类型的记录

    OPEN  c_CursorRef FOR

     SELECT author_code,name FROM auths;

    

     FECTCH c_CursorRef INTO v_Author;

     WHILE c_CursorRef%FOUND LOOP

           ...

           FETCH c_CursorRef INTO v_Author;

     END LOOP;

   

     CLOSE c_CursorRef;

 

     OPEN c_CursorRef FOR

     SELECT  author_code,title FROM ariticle

      FETCH c_CursorRef INTO v_Article;

     WHILE c_CursorRef%FOUND LOOP

                   ...

            FETCH c_CursorRef INTO v_Article;

    END LOOP;

   

    CLOSE c_CursorRef;

END;

 

 

注意,在上例中,第一次关闭游标变量是可以省略的,因为在第二次打开游标变量是,就将第一次的查询丢失掉了.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值