Bulk Collect特性可以让我们在PL/SQL中能使用批查询,批查询在某些情况下能显著提高查询效率。

  • BULK COLLECT 子句会批量检索结果,即一次性将结果集绑定到一个集合变量中,并从SQL引擎发送到PL/SQL引擎。

  • 可以在select into,fetch into,returning into语句使用bulk collect。

  • 注意在使用bulk collect时,所有的into变量都必须是collections。

1. 背景

以前曾经做过一个需求,数据库中有两张表,A表是2千万记录,B表是1千万条记录,它们之间存在某种联系,要求程序将它们关联起来,以A表为基准。

然后就是PL/SQL写了个程序(参考方式一代码),运行巨慢,且会报内存不足(在自己的笔记本上跑的)。后来用了BULK COLLECT,有了很大改善。以前的代码已经没有了运行的环境,代码也只保留了框架下来,贴在这里,做个记号。

方式一,最早的实现方式:

DECLARE
--定义一个RECORD类型用来存储记录,为节省内存,只存储需要处理的字段
TYPE SIM_RECORD is record(
SYSCODE SIM.SYSCODE%TYPE,
CUSNAME SIM.CUSNAME%TYPE,
CUSADDR SIM.CUSADDR%TYPE,
PHONE SIM.PHONE%TYPE
);
V_SIM_RECORD SIM_RECORD; --定义若干用到的其它变量
v_start_syscode number := 1;
v_process_records number := 1000000;
v_count number := 0; --定义游标
CURSOR SIMCursor IS SELECT SYSCODE,CUSNAME,CUSADDR,PHONE
FROM SIM
WHERE SYSCODE>=v_start_syscode AND SYSCODE<v_start_syscode+v_process_records;
BEGIN
  
--打开游标
OPEN SIMCursor;
LOOP
--读取游标
FETCH SIMCursor INTO V_SIM_RECORD;
EXIT WHEN SIMCursor%NOTFOUND; --防止更新出现异常,所以将DML语句进行封装,以避免某条记录出现错误而导致退出循环
BEGIN
--主处理语句,省略
--取得值通过:V_SIM_RECORD.SYSCODE等这样的方式获取 --每处理20000条记录,输出一些统计信息
v_count := v_count+1;
IF mod(v_count,20000)=0 THEN
dbms_output.put_line(V_SIM_RECORD.SYSCODE||'['||v_count||']');
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('sqlerrm-->' ||sqlerrm);
END;
END LOOP;
--关闭游标
CLOSE SIMCursor;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('sqlerrm-->' ||sqlerrm);
END;

方式二,在select into语句中使用bulk collect

DECLARE
--定义存储数据的数据结构(collections)
TYPE SIM_TABLE IS TABLE OF SIM%ROWTYPE;
T_SIM_TABLE SIM_TABLE; --定义若干用到的其它变量
v_start_syscode number := 1;
v_process_records number := 1000000;
v_count number := 0; BEGIN
--在select into语句中使用bulk collect,一次性取得
SELECT * BULK COLLECT INTO T_SIM_TABLE FROM SIM WHERE SYSCODE>=v_start_syscode AND SYSCODE<v_start_syscode+v_process_records; FOR i IN 1 .. T_SIM_TABLE.count LOOP --防止更新出现异常,所以将DML语句进行封装,以避免某错误记录导致退出循环
BEGIN
--主处理语句,省略
--取得值通过:T_SIM_TABLE(i).PHONE等这样的方式获取 --每处理20000条记录,输出一些统计信息
v_count := v_count+1;
IF mod(v_count,20000)=0 THEN
dbms_output.put_line(T_SIM_TABLE(i).PHONE||'['||v_count||']');
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('sqlerrm-->' ||sqlerrm);
END; END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('sqlerrm-->' ||sqlerrm);
END;

方式三,在fetch into中使用bulk collect

DECLARE
--定义存储数据的数据结构(collections)
TYPE SIM_TABLE IS TABLE OF SIM%ROWTYPE;
T_SIM_TABLE SIM_TABLE; --定义若干用到的其它变量
v_start_syscode number := 1;
v_process_records number := 1000000;
v_count number := 0; --定义游标
CURSOR SIMCursor IS SELECT * FROM SIM where SYSCODE>=v_start_syscode AND SYSCODE<v_start_syscode+v_process_records;
BEGIN
OPEN SIMCursor;
LOOP
EXIT WHEN SIMCursor%NOTFOUND;
--在fetch into中使用bulk collect,分批次取得
FETCH SIMCursor BULK COLLECT INTO T_SIM_TABLE LIMIT 50000; FOR i IN 1 .. T_SIM_TABLE.count LOOP --防止更新出现异常,所以将DML语句进行封装,以避免某错误记录导致退出循环
BEGIN
--主处理语句,省略
--取得值通过:T_SIM_TABLE(i).PHONE等这样的方式获取 --每处理20000条记录,输出一些统计信息
v_count := v_count+1;
IF mod(v_count,20000)=0 THEN
dbms_output.put_line(T_SIM_TABLE(i).PHONE||'['||v_count||']');
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('sqlerrm-->' ||sqlerrm);
END;
END LOOP; END LOOP;
CLOSE SIMCursor;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('sqlerrm-->' ||sqlerrm);
END;

Oracle学习笔记之五sp1,PL/SQL之BULK COLLECT的更多相关文章

  1. Oracle学习笔记十 使用PL/SQL

    PL/SQL 简介 PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用 ...

  2. oracle学习笔记4:PL/SQL

    PL/SQL是没命名的存储过程,函数,触发器,PL/SQL块的语法格式如下: [declare] --声明部分,可选 begin --执行部分,必须 [exception] --异常处理部分,可选 e ...

  3. Oracle 学习笔记 17 -- 异常处理(PL/SQL)

    程序异常是在操作期间正常,出现在节目的准备过程是不可避免的例外.但是,必须有一个相应的异常处理机 制,以保证程序的正常运行.PL/SQL程序运行过程中出现的错误.称为异常. 一个优秀的程序都应该可以正 ...

  4. Oracle学习笔记之四sp1,Oracle 11g的常用函数

    从Oracle学习笔记之四,SQL语言入门中摘出来的,独立成一章节 3.1 字符类函数 ASCII(c)和CHR(i)    分别用于返回一个字符的ASCII码和返回给定ASCII值所对应的字符. C ...

  5. ORACLE PL/SQL开发--bulk collect的用法 .

    刚刚在inthirties老大的博客里看到这篇文章,写的不错,正好自己最近在学习PL/SQL,转过来学习学习. ============================================ ...

  6. Oracle学习笔记之五,Oracle 11g的PL/SQL入门

    1. PL/SQL概述 PL/SQL(Procedural Language/SQL)是Oracle的专用语言,是对标准SQL语言的扩展,它允许在其内部嵌套普通的SQL语句,还可以定义变量和常量,允许 ...

  7. oracle学习(二)pl/sql基础

    pl/sql组成:DDL DML DCL pl/sql特点: SQL&PL/SQL编译器集成PL/SQL,支持SQL所有范围的语法 支持CASE语句和表达式 继承和动态方法释放 类型进化.属性 ...

  8. oracle 学习(五)pl/sql语言存储过程&包

    首先搞清楚俩概念 存储过程(procedure)&程序包(package) 存储过程:数据库对象之一,可以理解为数据库的子程序,在客户端和服务器端可以直接调用它.触发器是与表直接关联的特殊存储 ...

  9. oracle学习笔记(九) SQL常用函数说明以及使用

    SQL常用函数说明以及使用 以下补充以下常用的函数,更多的请看oracle函数API文档 to_char to_char(8.58,'9.99') to_char(8.50,'9.00') to_ch ...

随机推荐

  1. 【Nodejs】“快算24”扑克牌游戏算法 1.01

    考虑到1.00版本需要改源码变更四个数字,这版修改了一下变成控制台输入了. 先把两个数四则运算得到结果想清楚就是C2代码,三个数就是C3,四个数就是C4.简单的代码简单,却是复杂的基础:复杂的脱胎于简 ...

  2. CentOS6.X下安装配置独立SVN服务器Subversion server

    Subversion(简称SVN,svn),一个开放源码的版本号控制系统.相较于RCS.CVS,它採用了分支管理系统,它的设计目标就是代替CVS.互联网上非常多版本号控***务已从CVS转移到Subv ...

  3. nm 命令 程序符号信息查看

    http://www.cnblogs.com/wangkangluo1/archive/2012/07/02/2572438.html 用途 显示关于对象文件.可执行文件以及对象文件库里的符号信息. ...

  4. PHP高级教程-文件上传

    PHP 文件上传 通过 PHP,可以把文件上传到服务器. 本章节实例在 test 项目下完成,目录结构为: test |-----upload # 文件上传的目录 |-----form.html # ...

  5. GraphQL返回分页对象

    private GraphQLOutputType testUserOutputType; private GraphQLOutputType pageType; private void initO ...

  6. 转:Python yield 使用浅析

    初学 Python 的开发者经常会发现很多 Python 函数中用到了 yield 关键字,然而,带有 yield 的函数执行流程却和普通函数不一样,yield 到底用来做什么,为什么要设计 yiel ...

  7. bg和fg命令

    linux提供的fg和bg命令,可以让我们轻松调度正在运行的任务   假如你发现前天运行的一个程序需要很长的时间,但是需要干前天的事情,你就可以用ctrl-z挂起这个程序,然后可以看到系统的提示: [ ...

  8. Flash打开新窗口 被浏览器拦截问题 navigateToURL被拦截 真正试验结果

    众所周知,打开新窗口以前经常被用作弹出广告用,而随着浏览器发展,现在估计除了ie6之外,基本都有广告拦截功能,最基本就是拦截这种非人为的弹出新窗口.我对js研究不深,我所了解就是,必须是用户操作的处理 ...

  9. centos7 开启ftp服务

    1.关闭默认防火墙 systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewa ...

  10. CAS 5.1.x 的搭建和使用(四)—— 配置使用HTTP协议访问的服务端

    CAS单点登录系列: CAS 5.1.x 的搭建和使用(一)—— 通过Overlay搭建服务端 CAS5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明 CAS5.1.x ...