`

Oracle学习笔记整理之游标篇

阅读更多

转自:http://www.itpub.net/thread-1394528-1-1.html

游标分为隐式、显式、REF三种游标。
而隐式游标和显式游标又都属于静态游标,REF游标属于动态游标。
静态游标和动态游标的最大区别在于静态游标是在运行前将游标变量和SQL关联,而动态游标恰恰相反是在运行后将游标变量和SQL进行关联。
隐式游标是由Oracle自动管理,也称sql游标。所有的DML都被Oracle解析成为一个名为SQL的隐式游标。DML包括Insert、Delete、Update、Merge into。而Select属于DQL。
隐式游标的属性有:

属性名                 说明

sql%found 影响行数大于等于1是为 ture

sql%notfound 没有影响行是为true

sql%rowcount 受影响的行数

sql%isopen 游标是否打开,始终为false

sql%bulk_rowcount(index) ...

sql%bulk_exceptions(index).error_index ...

sql%bulk_exceptions(index).error_code


隐式游标实例:
begin
  --执行DML操作
  update chg_test_b b set b.chg_name = 'ff' where b.chg_id = 5;
  --判断是否有受影响行
  if sql%found then
    --打印受影响行数
    dbms_output.put_line('影响行数:' || sql%rowcount);
  end if;
  --判断是否没有受影响行
  if sql%notfound then
    dbms_output.put_line('id为5的记录不存在');
  end if; 
end;
无参显式游标实例:
declare
  --声明游标表变量并关联sql
  cursor rowList is
    select * from chg_test_b b;
  --声明行变量
  --如果上面的查询语句只有一个查询字段,这里也可以使用正常的变量声明方式(v_rowValue varchar2(20);)。
  rowValue chg_test_b%rowtype;
begin
  open rowList; --打开游标
  --如果确定由表中只有一条记录的话,loop和end loop可以不写,而exit必须存在于游标循环内,所以也不需要写。
  loop
    fetch rowList
      into rowValue; --取出游标内的值放到rowValue中
    exit when rowList%notfound; --判断是否还存在记录,如果不存在终止游标
    dbms_output.put_line(rowValue.chg_name); --将的到的值打印,如果查询只有一个字段这里只需写变量名即可。
  end loop;
  close rowList; --关闭游标
end;
有参显式游标实例:
declare
  --声明带参数的游标变量并关联sql,并将参数与sql进行关联
  cursor rowList(c_name varchar2, c_id number) is
    select * from chg_test_b b where b.chg_name = c_name and b.chg_id = c_id;
  --声明行变量
  --如果上面的查询语句只有一个查询字段,这里也可以使用正常的变量声明方式(v_rowValue varchar2(20);)。
  rowValue chg_test_b%rowtype;
begin
  open rowList('chg1', 1); --打开游标,并将参数给出
  --如果确定由表中只有一条记录的话,loop和end loop可以不写,而exit必须存在于游标循环内,所以也不需要写。
  loop
    fetch rowList
      into rowValue; --取出游标内的值放到rowValue中
    exit when rowList%notfound;--判断是否还存在记录,如果不存在终止游标
    dbms_output.put_line(rowValue.chg_name); --将的到的值打印,如果查询只有一个字段这里只需写变量名即可。
  end loop;
  close rowList; --关闭游标
end;
在游标内进行DML操作实例:
declare
  --声明游标变量,并关联sql
  --如果要在游标内执行DML操作,必须使用for update。
  --使用for update后你所操作的行或列将会被锁,如果这时其他人操作就会进入等待状态。
  --如果你在执行select时记录被锁,那么就会进入等待状态,
  --为了避免这种情况可以在 for update后使用 nowait,这样你的结果就可以立即返回,但不建议使用
  --如果被锁在打开游标时会报出ORA-00054资源正忙异常,需捕获异常进行处理
  --使用of的区别时锁字段和锁行。
  cursor rowList is
    select b.* from chg_test_b b for update of b.chg_name nowait;
  --如果上面的查询语句只有一个查询字段,这里也可以使用正常的变量声明方式(v_rowValue varchar2(20);)。
  rowValue chg_test_b%rowtype;
  v_i      number(11);
begin
  v_i := 1;
  open rowList; --打开游标
  --如果确定由表中只有一条记录的话,loop和end loop可以不写,而exit必须存在于游标循环内,所以也不需要写。
  loop
    fetch rowList
      into rowValue; --取出游标内的值放到rowValue中
    exit when rowList%notfound;--判断是否还存在记录,如果不存在终止游标
    dbms_output.put_line(rowValue.chg_name); --将的到的值打印,如果查询只有一个字段这里只需写变量名即可。
    --执行DML操作
    update chg_test_b b
       set b.chg_name = 'chg' || v_i
     where current of rowList;
    v_i := v_i + 1;
  end loop;
  close rowList; --关闭游标
  commit;
end;
循环游标实例:
循环游标不需要手动进行打开和管理操作,全部由oracle进行管理。for yy in xx 等同于fetch xx into yy;
declare
  --声明游标变量并关联sql
  cursor rowList is
    select level a from dual connect by level <= 10;
begin
  for rowValue in rowList loop
    --rowValue是每条记录不需要事先声明,rowList是集合中的所有记录
    dbms_output.put_line(rowValue.a);--取出集合中的值进行打印
  end loop;
end;


declare
begin
  --可以将select语句for xx in 内,无论传参或是嵌套更为方便简洁。
  for rowValue in (select level a from dual connect by level <=10) loop
     for rv in (select col1 from tab1 where tab1.id = rowValue.a) loop
         dbms_output.put_line(rv.col1 );--将的到的值打印。
     end loop;
  end loop;
end;


declare
begin
  for rowValue in 1..10 loop
    dbms_output.put_line(rowValue);--将的到的值打印,如果查询只有一个字段这里只需写变量名即可。
  end loop;
end;
REF游标实例:
declare
  type cus_cur_type is ref cursor return chg_test_b%rowtype; --强类型Ref游标,查询的sql必须返回chg_test_b表类型
   --type cus_cur_type is ref cursor;弱类型Ref游标,返回类型没有限制
  rowList cus_cur_type; -- 声明游标变量
  rowValue chg_test_b%rowtype; --声明行变量
begin
  open rowList for --打开游标,并关联sql
    select * from chg_test_b b;
  loop
    fetch rowList
      into rowValue; --按行取出数据
    exit when rowList%notfound;--判断是否还存在记录,如果不存在终止游标
    dbms_output.put_line(rowValue.chg_name);--将的到的值打印,如果查询只有一个字段这里只需写变量名即可。
  end loop;
  close rowList;--关闭游标
end;

 

 

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

CREATE TABLE T (N1 NUMBER,C1 VARCHAR2(1));


INSERT INTO T VALUES (1,NULL);

INSERT INTO T VALUES (2,NULL);

INSERT INTO T VALUES (2,NULL);

INSERT INTO T VALUES (3,NULL);

INSERT INTO T VALUES (3,NULL);

INSERT INTO T VALUES (3,NULL);

INSERT INTO T VALUES (4,NULL);

INSERT INTO T VALUES (4,NULL);


----sql%bulk_rowcount(index)使用例子

DECLARE

   TYPE num_t IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

   lv_num num_t;

BEGIN

   lv_num(1):=2;

   lv_num(2):=3;

   lv_num(3):=4;

   lv_num(4):=1;

   

   FORALL i IN 1..lv_num.COUNT  ---- 批量执行UPDATE, 里面其实有三个UPDATE

      UPDATE t SET c1=n1 WHERE n1=lv_num(i);

   

   FOR i IN 1..lv_num.COUNT LOOP

       --- SQL%ROWCOUNT(i)告诉你每个UPDATE执行了多少行

       DBMS_OUTPUT.PUT_LINE('n1='||lv_num(i)||' '||SQL%BULK_ROWCOUNT(i)||' rows updated');

   END LOOP;

END;

/


输出:

n1=2 2 rows updated

n1=3 3 rows updated

n1=4 2 rows updated

n1=1 1 rows updated



PL/SQL procedure successfully completed.



SELECT * FROM T;



        N1 C

---------- -

         1 1

         2 2

         2 2

         3 3

         3 3

         3 3

         4 4

         4 4


8 rows selected.


---- sql%bulk_exceptions(index).error_index sql%bulk_exceptions(index).error_code 使用例子

DECLARE

   TYPE num_t IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

   lv_num num_t;


   dml_errors EXCEPTION;

   lv_err_cnt number := 0;

   PRAGMA exception_init(dml_errors, -24381);


BEGIN

   lv_num(1):=2;

   lv_num(2):=3;

   lv_num(3):=4;

   lv_num(4):=1;

               

   BEGIN

      FORALL i IN 1 .. lv_num.count SAVE EXCEPTIONS

         UPDATE t SET c1=n1*4 WHERE n1=lv_num(i);     --- n1*4 在n1=3和4的时候将会溢出,因为c1定义是VARCHAR2(1)

   EXCEPTION

       WHEN dml_errors THEN

            lv_err_cnt := SQL%BULK_EXCEPTIONS.COUNT;

            

            DBMS_OUTPUT.PUT_LINE('There are '||lv_err_cnt||' errors');

            

            FOR i IN 1..lv_err_cnt LOOP

                DBMS_OUTPUT.PUT_LINE('error number '||i

                                     ||' happened in index '||SQL%BULK_EXCEPTIONS(i).ERROR_INDEX  ---- lv_num数组的下标

                                     ||' data='||lv_num(SQL%BULK_EXCEPTIONS(i).ERROR_INDEX)

                                     ||' error code='||SQL%BULK_EXCEPTIONS(i).ERROR_CODE

                                     ||' error msg='||SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE) ---- 根据错误代码反推错误信息

                                     );

            END LOOP;

   END;

   

END pr_copy_data;

/


输出:

There are 2 errors

error number 1 happened in index 2 data=3 error code=12899 error msg=ORA-12899: value too large for column  (actual: , maximum: )

error number 2 happened in index 3 data=4 error code=12899 error msg=ORA-12899: value too large for column  (actual: , maximum: )


PL/SQL procedure successfully completed.



SELECT * FROM T;


        N1 C

---------- -

         1 4     ---- c1 被修改为 N1*4

         2 8     ---- c1 被修改为 N1*4

         2 8     ---- c1 被修改为 N1*4

         3 3     ---- 以下 c1 保持原样因为 N1*4 溢出了

         3 3

         3 3

         4 4

         4 4


8 rows selected.

 

分享到:
评论

相关推荐

    oracle学习笔记整理

    学习oracle知识笔记整理,包括pl/sql编程,过程、函数、游标开发等。

    ORACLE 游标学习笔记

    在PL/SQL中为所有SQL数据操纵语句(包括返回一行的select)隐式声明游标,称为隐式游标的原因是用户不能直接命名和控制此类游标.当用户在PL/SQL中使用数据操纵语言(DML)时,Oracle预先定义一个名为SQL的隐式游标

    oracle学习笔记(从入门到精通)

    压缩包主要包括15个文档,主要是本人学习oracle过程中的笔记,希望...08-PLSQL和游标结合学习笔记.txt 09-游标学习笔记.txt 10-重要的函数的学习笔记.txt 11-存储过程学习笔记.txt 12-触发器学习笔记.txt 13-pl编码.txt

    Oracle 10g 学习笔记

    │ Oracle学习笔记.pdf │ Oracle学习笔记.wps │ 安装Oracle后myEclipse不能正常使用.txt │ 手工配置listener.ora【避免出现ORA-12514错误】.txt │ 贴子树状态存储结构.jpg │ 贴子树状态存储结构.sql │ ├─01...

    oracle基础笔记整理

    Oracle基础学习笔记,开窗排序函数,权限管理,递归查询,存储函数触发器游标等等

    oracle学习笔记

    oracle数据库学习笔记,包括存储过程,游标...

    Oracle 入门文档

    Oracle笔记 九、PL/SQL 游标的使用 Oracle笔记 十、PL/SQL存储过程 Oracle笔记 十一、PL/SQL函数和触发器 Oracle笔记 十二、PL/SQL 面向对象oop编程 Oracle笔记 十三、PL/SQL面向对象之package Oracle笔记 十四...

    oracle pl的学习笔记

    自己总结的oracle pl学习代码。有游标,存储过程,触发器,集合等。 初步学习pl的话会有一些帮助,也提供了相关的练习。

    ORACLE学习笔记2:日常应用、深入管理、性能优化.

    第1篇 日常应用 第1章 安装和卸载 第2章 数据库管理 第3章 数据库实例管理 第4章 数据库安全管理 第5章 数据库逻辑存储结构管理 第6章 数据库物理文件管理 第7章 数据库逻辑对象管理 第8章 常用数据操纵语言 第...

    ORACLE_PlSql-甲骨文学习笔记

    三、ORACLE 10g新增的数据类型 4 说明 4 示例 4 特殊值 4 四、ORACLE PL/SQL简介 5 1 块结构 5 2 变量和类型 6 3 条件逻辑 6 4 循环 7 5 游标 8 №1声明一些变量,用于保存select语句的返回的列值 8 №2声明游标,并...

    oracle学习资料 里面有ppt和笔记 很详细

    详细介绍oracle表、分区、锁、视图、索引、循环、游标、游标、过程、函数、程序包、分离、触发器等等 非常实用 学习的朋友可以看看

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...

    oracle所有知识点笔记(全)

    这是我自己学习oracle的时候,写的代码案例和笔记,基本上每一个知识点都写的很清楚!大家可以作为参考! 该有的知识点都有! 基本的sql语法,触发器,存储过程,存储函数, 流程控制,游标,异常处理,记录类型,...

    Oracle笔记

    此笔记为个人通过自学所整理的oracle笔记,希望看到的人有什么建议告诉我,或者共同学习!里面内容主要包括:oracle增删改查、用户管理、索引、视图、PLSQL、存储过程、函数、游标、触发器等等!每个知识点都有案例...

    Java/JavaEE 学习笔记

    Oracle学习笔记...............121 前言....................................121 第一章 Selecting Rows.....................124 第二章 Limiting Selected Rows.......127 第三章 Single Row Functions.............

    oracle学习

    本文档是我学习oracle时的笔记。主要是oracle基础,存储过程,触发器,函数,游标,包等学习与实现,每个知识点有示例代码,供学习oracle用。

    Oracle开发笔记

    -个很详细很难得的Oracle学习资料,包含了序列建立,存储过程,大量的常用函数,异常处理,游标实现,各种语句的优化等等,全部都是以实例来讲解,有绝对价值的资料

    J2EE学习笔记(J2ee初学者必备手册)

    Oracle学习笔记...............121 前言....121 第一章 Selecting Rows.....................124 第二章 Limiting Selected Rows.......127 第三章 Single Row Functions..........127 第四章 Displaying Data from ...

    oracle学习大全-从简单的入门sql到复杂备份

    曾经的oracle笔记!!! 从第一章到最后一章。 从写简单sql到存储过程,游标,触发器到复杂备份!!! 你让见证曾经我走过的路!!! 下载完请点评等级并留言,不会被扣分。切记!

Global site tag (gtag.js) - Google Analytics