[20180110]Oracle Bulk Collect and Limit

简介: [20180110]Oracle's Bulk Collect and Limit.txt --//链接提到https://www.databasejournal.

[20180110]Oracle's Bulk Collect and Limit.txt

--//链接提到https://www.databasejournal.com/features/oracle/oracles-bulk-collect-and-limit-can-be-a-problem.html
--//如果Bulk Collect使用Limit,可能导致处理数据丢失,应该引起开发足够重视,我不知道开发是否喜欢这样处理事务或者这样
--//写PL/sql语句.自己改写例子来说明问题.

1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SCOTT@book> create table emp_test as select * from emp where 1=0;
Table created.

2.测试一:
$ cat limit.sql
DECLARE
   TYPE empcoltyp IS TABLE OF emp%ROWTYPE;
   emp_c   empcoltyp;
   CURSOR get_emp_data
   IS
      SELECT * FROM emp;
BEGIN
   OPEN get_emp_data;
   LOOP
      FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT &1;
      EXIT WHEN get_emp_data%NOTFOUND;
      --exit when emp_c.count = 0;
      FOR i IN 1 .. emp_c.COUNT
      LOOP
         DBMS_OUTPUT.put_line ( emp_c (i).empno || emp_c (i).ename || emp_c (i).sal);
         insert into emp_test (empno, ename, sal) values (emp_c(i).empno, emp_c(i).ename, emp_c(i).sal);
      END LOOP;
   END LOOP;
   commit;
END;
/

SCOTT@book> set serverout on
SCOTT@book> @ limit 9
old  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT &1;
new  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT 9;
7369SMITH800
7499ALLEN1600
7521WARD1250
7566JONES2975
7654MARTIN1250
7698BLAKE2850
7782CLARK2450
7788SCOTT3000
7839KING5000
7369SMITH800     =>再次输出一遍
7499ALLEN1600
7521WARD1250
7566JONES2975
7654MARTIN1250
7698BLAKE2850
7782CLARK2450
7788SCOTT3000
7839KING5000
PL/SQL procedure successfully completed.

SCOTT@book> select count(*) from emp_test;
COUNT(*)
----------
9

--//可以发现emp_test仅仅有9条记录。也就是漏处理了5条记录,而DBMS_OUTPUT.put_line的输出是18条(重复1次)
--//而使用参数7,正好整除,结果如下:

SCOTT@book> truncate table  emp_test ;
Table truncated.

SCOTT@book> @ limit 7
old  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT &1;
new  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT 7;
7369SMITH800
7499ALLEN1600
7521WARD1250
7566JONES2975
7654MARTIN1250
7698BLAKE2850
7782CLARK2450
7788SCOTT3000
7839KING5000
7844TURNER1500
7876ADAMS1100
7900JAMES950
7902FORD3000
7934MILLER1300
PL/SQL procedure successfully completed.

SCOTT@book> select count(*) from emp_test;
  COUNT(*)
----------
        14

--//我自己还是不理解DBMS_OUTPUT.put_line会重复输出(limit 9)。
--//注:错误在我自己的设置,参考链接:http://blog.itpub.net/267265/viewspace-2150028/
SCOTT@book> truncate table  emp_test ;
Table truncated.

SCOTT@book> @ limit 5
old  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT &1;
new  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT 5;
7369SMITH800
7499ALLEN1600
7521WARD1250
7566JONES2975
7654MARTIN1250
7698BLAKE2850
7782CLARK2450
7788SCOTT3000
7839KING5000
7844TURNER1500
PL/SQL procedure successfully completed.

SCOTT@book> select * from emp_test;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7369 SMITH                                                      800
      7499 ALLEN                                                     1600
      7521 WARD                                                      1250
      7566 JONES                                                     2975
      7654 MARTIN                                                    1250
      7698 BLAKE                                                     2850
      7782 CLARK                                                     2450
      7788 SCOTT                                                     3000
      7839 KING                                                      5000
      7844 TURNER                                                    1500
10 rows selected.

--//这样是正确的!!而limit 9就存在问题(那位能解析)。如果换成
EXIT WHEN get_emp_data%NOTFOUND;
修改为
exit when emp_c.count = 0;

---//执行结果就是正确的。具体解析可以看链接。

3.测试二:
--//换成forall看看,错误应该也是一样的。
$ cat limit1.sql
/* Formatted on 2018/1/10 9:57:46 (QP5 v5.252.13127.32867) */
DECLARE
   TYPE empcoltyp IS TABLE OF emp%ROWTYPE;
   emp_c   empcoltyp;
   CURSOR get_emp_data
   IS
      SELECT * FROM emp;
BEGIN
   OPEN get_emp_data;
   LOOP
      FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT &1;
      EXIT WHEN get_emp_data%NOTFOUND;
      --exit when emp_c.count = 0;
      --FORALL i IN 1 .. emp_c.COUNT
      --   DBMS_OUTPUT.put_line ( emp_c (i).empno || emp_c (i).ename || emp_c (i).sal);

      --FORALL i IN 1 .. emp_c.COUNT
      --   INSERT INTO emp_test (empno, ename, sal) VALUES (emp_c (i).empno, emp_c (i).ename, emp_c (i).sal);

      FORALL i IN emp_c.first .. emp_c.last
         INSERT INTO emp_test (empno, ename, sal) VALUES (emp_c (i).empno, emp_c (i).ename, emp_c (i).sal);
   END LOOP;
   COMMIT;
END;
/
--//forall不能执行DBMS_OUTPUT.put_line输出,仅仅能执行sql语句,好像仅仅1行语句。

--//测试:
SCOTT@book> truncate table  emp_test ;
Table truncated.

SCOTT@book> @ limit1 9
old  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT &1;
new  13:       FETCH get_emp_data BULK COLLECT INTO emp_c LIMIT 9;
PL/SQL procedure successfully completed.

SCOTT@book> select count(*) from emp_test;
  COUNT(*)
----------
         9

--//总之在具体开发中注意这个问题。

目录
相关文章
|
SQL Oracle 关系型数据库
[20180111]Oracle Bulk Collect and Limit2
[20180111]Oracle's Bulk Collect and Limit2.txt --//昨天在测试时遇到一个的奇怪问题,链接http://blog.itpub.net/267265/viewspace-2149969/,执行 --//@ limit 9 时,重复输出了2次。
1189 0
|
SQL Oracle 关系型数据库
Oracle数据库之FORALL与BULK COLLECT语句
Oracle数据库之FORALL与BULK COLLECT语句    我们再来看一下PL/SQL块的执行过程:当PL/SQL运行时引擎处理一块代码时,它使用PL/SQL引擎来执行过程化的代码,而将SQL语句发送给SQL引擎来执行;SQL引擎执行完毕后,将结果再返回给PL/SQL引擎。
1041 0
|
SQL 关系型数据库 Perl
PLSQL_性能优化系列11_Oracle Bulk Collect批处理
2014-10-04 Created By BaoXinjian 一、摘要 PL/SQL程序中运行SQL语句是存在开销的,因为SQL语句是要提交给SQL引擎处理。 这种在PL/SQL引擎和SQL引擎之间的控制转移叫做上下文却换,每次却换时,都有额外的开销。
1155 0
|
SQL 关系型数据库 计算机视觉
Oracle bulk 示例
Oracle有2个引擎来执行PL/SQL blocks 和 subprograms。那么在执行的时候,PL/SQL 引擎把DML 语句发送给SQL 引擎,然后由SQL 引擎执行,执行完毕后,SQL 引擎把结果集在发送给PL/SQL 引擎。
919 0
|
9月前
|
Oracle 关系型数据库 Linux
【赵渝强老师】Oracle数据库配置助手:DBCA
Oracle数据库配置助手(DBCA)是用于创建和配置Oracle数据库的工具,支持图形界面和静默执行模式。本文介绍了使用DBCA在Linux环境下创建数据库的完整步骤,包括选择数据库操作类型、配置存储与网络选项、设置管理密码等,并提供了界面截图与视频讲解,帮助用户快速掌握数据库创建流程。
759 93
|
8月前
|
Oracle 关系型数据库 Linux
【赵渝强老师】使用NetManager创建Oracle数据库的监听器
Oracle NetManager是数据库网络配置工具,用于创建监听器、配置服务命名与网络连接,支持多数据库共享监听,确保客户端与服务器通信顺畅。
411 0
|
11月前
|
存储 Oracle 关系型数据库
服务器数据恢复—光纤存储上oracle数据库数据恢复案例
一台光纤服务器存储上有16块FC硬盘,上层部署了Oracle数据库。服务器存储前面板2个硬盘指示灯显示异常,存储映射到linux操作系统上的卷挂载不上,业务中断。 通过storage manager查看存储状态,发现逻辑卷状态失败。再查看物理磁盘状态,发现其中一块盘报告“警告”,硬盘指示灯显示异常的2块盘报告“失败”。 将当前存储的完整日志状态备份下来,解析备份出来的存储日志并获得了关于逻辑卷结构的部分信息。
|
9月前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
602 8
|
11月前
|
SQL Oracle 关系型数据库
比较MySQL和Oracle数据库系统,特别是在进行分页查询的方法上的不同
两者的性能差异将取决于数据量大小、索引优化、查询设计以及具体版本的数据库服务器。考虑硬件资源、数据库设计和具体需求对于实现优化的分页查询至关重要。开发者和数据库管理员需要根据自身使用的具体数据库系统版本和环境,选择最合适的分页机制,并进行必要的性能调优来满足应用需求。
509 11

推荐镜像

更多