`

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自动管理的一种游标,主要用于DML(数据操纵语言)...

    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基础学习笔记涵盖了数据库管理的核心要素,从基本的SQL语法到复杂的存储过程和触发器,再到权限控制和递归查询,都是数据库管理员和开发人员必备的知识点。深入理解和熟练运用这些概念,将有助于你...

    oracle学习笔记,介绍详细

    这份“Oracle学习笔记”无疑是你深入理解和掌握Oracle技术的重要资源。笔记涵盖了Oracle的语法基础、核心概念以及各种实用功能,旨在帮助初学者快速上手,同时也能为有一定经验的DBA提供参考。 首先,Oracle数据库...

    MLDN_Oracle学习笔记+源码 李兴华讲解

    《MLDN_Oracle学习笔记+源码 李兴华讲解》是针对Oracle数据库系统的一份详尽学习资源,由知名讲师李兴华精心编撰。这份资料不仅包含了丰富的理论知识,还提供了源代码实例,旨在帮助学习者深入理解和掌握Oracle...

    Oracle学习笔记.doc

    ### Oracle学习笔记知识点详解 #### 一、SQL概述与Oracle简介 - **SQL**(Structured Query Language,结构化查询语言)是一种用于管理关系型数据库的标准语言。它被用来执行各种数据库操作,如查询数据、更新数据...

    韩顺平2011oracle学习笔记

    【Oracle的基础使用与基本命令】 ...以上只是Oracle学习笔记的一部分,实际学习中还包括索引、视图、存储过程、触发器、游标、事务控制等多个方面的内容,都需要深入理解和实践才能掌握Oracle数据库的精髓。

    oracle 学习笔记资料

    Oracle是世界上最广泛使用的数据库管理系统之一...以上就是根据给定文件名推测的Oracle学习笔记资料可能涵盖的主要知识点。通过深入学习和实践,可以掌握Oracle数据库的使用和管理,从而在IT领域中提升自己的专业能力。

    Oracle学习笔记(一天就可以学会,学不会你骂我)

    Oracle学习笔记:一天掌握核心概念 Oracle数据库系统是全球广泛使用的数据库管理系统之一,以其高效、稳定和可扩展性而著称。本教程旨在帮助你快速理解Oracle的基本概念和操作,让你在一天之内能够掌握关键知识。 ...

    Oracle SQLServer数据库 学习笔记

    这篇学习笔记将深入探讨这两个系统的概念、特性和应用。 一、Oracle数据库系统 Oracle数据库是由甲骨文公司开发的一款强大、高性能的数据库解决方案。其主要特点包括: 1. **分布式数据库**:Oracle支持多节点的...

    Oracle学习笔记——day01

    在Oracle学习的第一天,我们主要关注了SQL语句,这是与Oracle交互的基础。SQL主要包括三种类型的语言:DML(数据操作语言)、DDL(数据定义语言)和DCL(数据控制语言)。 1. **DML(数据操作语言)**:DML主要用于...

    oracle学习笔记

    Oracle学习笔记涵盖了数据库管理、SQL查询以及PL/SQL编程等多个方面。Oracle是全球最广泛使用的商业关系型数据库管理系统之一,其高效稳定性和强大的数据处理能力使其在企业级应用中占据了重要地位。以下是对"oracle...

    oracle最全学习笔记(个人总结)

    ### Oracle 最全学习笔记知识点梳理 #### 一、存储过程 - **定义**:存储过程是一种在数据库中存储复杂程序以便外部程序调用的一种数据库对象。 - **应用场景**:主要用于执行大量的更新或插入操作,以提高数据库...

    Oracle学习笔记

    以下是对“Oracle学习笔记”中可能包含的知识点的详细解释: 1. **Oracle数据库体系结构**:Oracle数据库的结构包括物理结构和逻辑结构。物理结构包括数据文件、控制文件、重做日志文件、初始化参数文件等;逻辑...

    自己的Oracle学习笔记

    以下是从标题、描述和部分内容中提炼出的Oracle学习笔记的关键知识点: 1. **Oracle基本配置**:Oracle默认监听的端口是1521,例如:`jdbc:oracle:thin:@127.0.0.1:1521:ORACLE`。用户可以使用如`scott/tiger`这样...

    韩顺平玩转oracle学习笔记

    ### 韩顺平玩转Oracle学习笔记知识点详解 #### 一、Oracle基本使用——基本命令 ##### 连接命令 - **`conn[ect]`**:此命令用于连接到Oracle数据库。语法如下: - `conn 用户名/密码@网络服务名 [as sysdba/...

    oracle_sql笔记

    这篇笔记主要涵盖了Oracle SQL的基础知识、高级特性和实际应用技巧。 一、基础SQL语法 Oracle SQL遵循标准的SQL语法,包括SELECT、INSERT、UPDATE、DELETE四大语句。用于查询数据的基本结构是SELECT字段列表FROM...

Global site tag (gtag.js) - Google Analytics