• 游标管理


    本节要点:

    • l  什么是游标
    • l  显式游标
    • l  隐式游标

    1         什么是游标

    游标的使用可以让用户像操作数组一样操作查询出来的数据集,这使得使用PL/SQL编程更加方便。实际上,它提供了一种从集合性质的结果中提取单条记录的手段。

    1.1       游标的概念

    可以简单地理解游标为指向结果集记录的指针,利用游标可以返回它当前指向的行记录(只能返回一行记录)。如果要返回多行,那么需要不断地滚动游标,把想要的数据查询一遍。用户可以操作游标所在位置行的记录。例如,把返回记录作为另一个查询的条件。

    1.2       游标的种类

    Oracle中游标分为静态游标和REF游标两类。其中,静态游标就像一个数据快照,打开游标后的结果集是对数据库数据的一个备份,数据不随着对表执行DML操作后改变。从这个特性来说,结果集市静态的。由于本人较懒,暂时不对REF游标做介绍。

    静态游标包含如下两种类型:

    显示游标:是指在使用之前必须有着明确的游标声明和定义,这样的游标定义会关联数据查询语句,通常会返回一行或多行。打开游标后,用户可以利用游标的位置对结果集进行检索,使之返回单一的行记录,用户可以操作此记录。关闭游标后,就不能再对结果集进行任何操作。显示游标需要用户自己写代码完成,一切由用户控制。

    隐式游标:和显示游标不同,它被PL/SQL自动管理,也被称为SQL游标。由Oracle自动管理。该游标用户无法控制,但能得到它的属性信息。

    2         显示游标

    通过显示游标用户可以操作返回的数据,使得一些在编程语言中复杂的功能变得更容易实现。

    游标语法:

    CURSOR cursor_name

    [(parameter_name datatype,…)]

       IS select_statement;

    • l  CURSOR cursor_name:声明游标,cursor_name是游标的名称
    • l  parameter_name:参数名称
    • l  datatype:参数类型
    • l  select_statement:游标关联的select语句,但该语句不能使select…into…语句

    游标的使用步骤:

    显示游标的使用顺序可以明确地分为声明游标、打开游标、读取数据和关闭游标四个步骤:

    1)         声明游标:用来给游标命名并且使得游标关联一个查询

    DECLARE CURSOR cursor_name IS SELECT_STATEMENT

    2)         打开游标:游标中任何对数据的操作都是建立在游标被打开的前提下。并且游标一旦打开,其结果集都是静态的,也就是说,此时结果集不会反映出数据库中对数据进行的增加、删除、修改操作。

    OPEN cursor_name

    3)         读取数据:利用FETCH语句完成,它可以把游标指向位置的记录放入到PL/SQL声明的变量当中。正常的情况下,FETCH要和循环语句一起使用。

    FETCH cursor_name INTO Record_Name

    4)         关闭游标:释放资源,结果集中的数据将不能做任何操作。

    CLOSE cursor_name

    循环游标用于简化游标处理代码,当用户需要从游标中提取所有记录时使用。

    语法:

    FOR <record_index> IN <cursor_name>

    LOOP

                    <executable statements>

    END LOOP;

    示例:

    declare

      v_name m_user.user_nm%type;/*声明v_name,与user_nm字段类型一致*/

      Cursor cur_stu Is/*定义游标cur_stu*/

         /*游标关联查询*/

        select t.user_nm from m_user t where t.user_owner_flg = 'M';

    begin

      Open cur_stu;/*打开游标*/

      Loop

        /*利用Fetch语句从结果集中提取指针指向的当前行记录*/

        Fetch cur_stu Into v_name;

        Exit When cur_stu%NotFound;/*集合循环完成时退出循环*/

        dbms_output.put_line('学生姓名:' || v_name);

      End Loop;

      Close cur_stu;/*关闭游标*/

    end;

    示例:带参数的显示游标

    DECLARE

      flag    VARCHAR2(20);

      s_code VARCHAR2(5);

      s_name    VARCHAR2(20);

      CURSOR stu(user_owner_flg VARCHAR2) IS

        SELECT t.user_cd, t.user_nm FROM m_user t WHERE t.user_owner_flg = flag;

    BEGIN

      flag := '&flag';

      OPEN stu(flag);

      LOOP

        FETCH stu

          INTO s_code, s_name;

        EXIT WHEN stu%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE(s_code || ' ' || s_name);

      END LOOP;

      CLOSE stu;

    END;

    3         隐式游标

    没有显示游标一样的可操作性,但是也经常用到。

    特点:

    • 在PL/SQL中使用DML语句时自动创建隐式游标
    • 隐式游标自动声明、打开和关闭,默认名称是SQL
    • Select或DML操作产生隐式游标
    • 隐式游标的属性值始终是最新执行的SQL语句

    游标的属性有:

    • %FOUND – SQL 语句影响了一行或多行时为 TRUE
    • %NOTFOUND – SQL 语句没有影响任何行时为TRUE
    • %ROWCOUNT – SQL 语句影响的行数
    • %ISOPEN  - 游标是否打开,始终为FALSE

    示例:只有在 DML 语句影响一行或多行时,才返回 True

    BEGIN

      UPDATE m_user t SET t.user_nm = '张三丰' WHERE t.user_cd = '1';

      IF SQL%FOUNDTHEN

        DBMS_OUTPUT.PUT_LINE('表已更新');

      END IF;

    END;

    示例:如果 DML 语句不影响任何行,则返回 True

    DECLARE

      v_id   m_user.user_cd%type := '&id';

      v_name m_user.user_nm%Type := '&name';

    BEGIN

      UPDATE m_user SET user_nm = v_name WHERE user_cd = v_id;

      IF SQL%NOTFOUNDTHEN

        DBMS_OUTPUT.PUT_LINE('编号未找到。');

      ELSE

        DBMS_OUTPUT.PUT_LINE('表已更新');

      END IF;

    END;

    示例:返回 DML 语句影响的行数

    begin

      update m_user t set t.user_nm = 'CHE' where t.user_cd = 1;

      if SQL%Found then

        dbms_output.put_line('修改记录数为:' || SQL%RowCount);

      else

        dbms_output.put_line('未找到相应记录');

      end if;

    end;

    示例:如果没有与SELECT INTO语句中的条件匹配的行,将引发NO_DATA_FOUND异常

    DECLARE

      v_id   m_user.user_cd%type;

      v_name m_user.user_nm%type;

    BEGIN

      v_id := '&id';

      SELECT t.user_nm INTO v_name FROM m_user t WHERE t.user_cd = v_id;

      DBMS_OUTPUT.PUT_LINE(v_name);

    EXCEPTION

      WHEN NO_DATA_FOUND THEN

        DBMS_OUTPUT.PUT_LINE('课程未找到');

    END;

    示例:如果 SELECT INTO 语句返回多个值,将引发TOO_MANY_ROWS异常

    DECLARE

      v_flag   m_user.user_owner_flg%type;

      v_name m_user.user_nm%type;

    BEGIN

      v_flag := '&flag';

      SELECT t.user_nm INTO v_name FROM m_user t WHERE t.user_owner_flg = v_flag;

      DBMS_OUTPUT.PUT_LINE(v_name);

    EXCEPTION

      WHEN TOO_MANY_ROWS THEN

            DBMS_OUTPUT.PUT_LINE('该查询提取多行');

    END;

  • 相关阅读:
    利用pipe实现进程通信一例
    司机和售票员问题 信号signal注册一例
    HDU 1003
    HDU 1847
    HDU 1846(巴什博弈)
    《断弦》感想
    夺冠概率
    熄灯问题
    HDU 2176(Nim博弈)
    NYOJ 541
  • 原文地址:https://www.cnblogs.com/zhouyeqin/p/7364644.html
Copyright © 2020-2023  润新知