ORACLE 10G OFFICIAL DOCUMNET 

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

一 介绍:

1、语法

for all statement ::=

bounds_clause ::=

2、关键字与参数介绍:

==index_name:一个无需声明的标识符,作为集合下标使用;

==sql_statement:静态语句,例如:UPDATE或者DELETE;或者动态(EXECUTE IMMEDIATE)DML语句。

==SAVE EXCEPTIONS:可选关键字,表示即使一些DML语句失败,直到FORALL loop执行完毕才抛出异常。可以使用SQL%BULK_EXCEPTIONS 查看异常信息。

==lower_bound .. upper_bound:数字表达式,来指定一组连续有效的索引数字。该表达式只需解析一次。

==INDICES OF collection_name:用于指向稀疏数组的实际下标

==VALUES OF index_collection_name:用于指向集合的一个子集的下标数组

二 使用FORALL:

1、循环中声明删除语句(Issuing DELETE Statements in a Loop

CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 30, 70); -- department numbers
BEGIN
FORALL i IN depts.FIRST..depts.LAST
DELETE FROM employees_temp WHERE department_id = depts(i);
COMMIT;
END;
/

2、循环中声明插入语句(Issuing INSERT Statements in a Loop)

CREATE TABLE parts1 (pnum INTEGER, pname VARCHAR2(15));
CREATE TABLE parts2 (pnum INTEGER, pname VARCHAR2(15));
DECLARE
TYPE NumTab IS TABLE OF parts1.pnum%TYPE INDEX BY PLS_INTEGER;
TYPE NameTab IS TABLE OF parts1.pname%TYPE INDEX BY PLS_INTEGER;
pnums NumTab;
pnames NameTab;
iterations CONSTANT PLS_INTEGER := 50000;
t1 INTEGER;
t2 INTEGER;
t3 INTEGER;
BEGIN
FOR j IN 1..iterations LOOP -- load index-by tables
pnums(j) := j;
pnames(j) := 'Part No. ' || TO_CHAR(j);
END LOOP;
t1 := DBMS_UTILITY.get_time;
FOR i IN 1..iterations LOOP -- use FOR loop
INSERT INTO parts1 VALUES (pnums(i), pnames(i));
END LOOP;
t2 := DBMS_UTILITY.get_time;
FORALL i IN 1..iterations -- use FORALL statement
INSERT INTO parts2 VALUES (pnums(i), pnames(i));
t3 := DBMS_UTILITY.get_time;
DBMS_OUTPUT.PUT_LINE('Execution Time (secs)');
DBMS_OUTPUT.PUT_LINE('---------------------');
DBMS_OUTPUT.PUT_LINE('FOR loop: ' || TO_CHAR((t2 - t1)/100));
DBMS_OUTPUT.PUT_LINE('FORALL: ' || TO_CHAR((t3 - t2)/100));
COMMIT;
END;
/

FORALL要明显快于FOR..LOOP结构:

Execution Time (secs)
---------------------
FOR loop: 5.14
FORALL: .56 PL/SQL 过程已成功完成。

3、集合部分元素使用FORALL(Using FORALL with Part of a Collection)

DROP TABLE employees_temp;
CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS VARRAY(10) OF NUMBER;
depts NumList := NumList(5,10,20,30,50,55,57,60,70,75);
BEGIN
FORALL j IN 4..7 -- use only part of varray
DELETE FROM employees_temp WHERE department_id = depts(j);
COMMIT;
END;
/

4、对非连续索引值使用FORALL(Using FORALL with Non-Consecutive Index Values)

-- Create empty tables to hold order details
CREATE TABLE valid_orders (cust_name VARCHAR2(32), amount NUMBER(10,2));
CREATE TABLE big_orders AS SELECT * FROM valid_orders WHERE 1 = 0;
CREATE TABLE rejected_orders AS SELECT * FROM valid_orders WHERE 1 = 0;
DECLARE
-- Make collections to hold a set of customer names and order amounts.
SUBTYPE cust_name IS valid_orders.cust_name%TYPE;
TYPE cust_typ IS TABLe OF cust_name;
cust_tab cust_typ;
SUBTYPE order_amount IS valid_orders.amount%TYPE;
TYPE amount_typ IS TABLE OF NUMBER;
amount_tab amount_typ;
-- Make other collections to point into the CUST_TAB collection.
TYPE index_pointer_t IS TABLE OF PLS_INTEGER;
big_order_tab index_pointer_t := index_pointer_t();
rejected_order_tab index_pointer_t := index_pointer_t();
PROCEDURE setup_data IS BEGIN
-- Set up sample order data, including some invalid orders and some 'big' orders.
cust_tab := cust_typ('Company1','Company2','Company3','Company4','Company5');
amount_tab := amount_typ(5000.01, 0, 150.25, 4000.00, NULL);
END; BEGIN
setup_data(); --initialization
DBMS_OUTPUT.PUT_LINE('--- Original order data ---');
FOR i IN 1..cust_tab.LAST LOOP
DBMS_OUTPUT.PUT_LINE('Customer #' || i || ', ' || cust_tab(i) || ': $' ||
amount_tab(i));
END LOOP;
-- Delete invalid orders (where amount is null or 0).
FOR i IN 1..cust_tab.LAST LOOP
IF amount_tab(i) is null or amount_tab(i) = 0 THEN
cust_tab.delete(i);
amount_tab.delete(i);
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE('--- Data with invalid orders deleted ---');
FOR i IN 1..cust_tab.LAST LOOP
IF cust_tab.EXISTS(i) THEN
DBMS_OUTPUT.PUT_LINE('Customer #' || i || ', ' || cust_tab(i) || ': $' ||
amount_tab(i));
END IF;
END LOOP;
-- Because the subscripts of the collections are not consecutive, use
-- FORALL...INDICES OF to iterate through the actual subscripts,
-- rather than 1..COUNT
FORALL i IN INDICES OF cust_tab
INSERT INTO valid_orders(cust_name, amount)
VALUES(cust_tab(i), amount_tab(i)); -- Now process the order data differently
-- Extract 2 subsets and store each subset in a different table
setup_data(); -- Initialize the CUST_TAB and AMOUNT_TAB collections again.
FOR i IN cust_tab.FIRST .. cust_tab.LAST LOOP
IF amount_tab(i) IS NULL OR amount_tab(i) = 0 THEN
rejected_order_tab.EXTEND; -- Add a new element to this collection
-- Record the subscript from the original collection
rejected_order_tab(rejected_order_tab.LAST) := i;
END IF;
IF amount_tab(i) > 2000 THEN
big_order_tab.EXTEND; -- Add a new element to this collection
-- Record the subscript from the original collection
big_order_tab(big_order_tab.LAST) := i;
END IF;
END LOOP;
-- Now it's easy to run one DML statement on one subset of elements,
-- and another DML statement on a different subset.
FORALL i IN VALUES OF rejected_order_tab
INSERT INTO rejected_orders VALUES (cust_tab(i), amount_tab(i));
FORALL i IN VALUES OF big_order_tab
INSERT INTO big_orders VALUES (cust_tab(i), amount_tab(i));
COMMIT;
END;
/
--- Original order data ---
Customer #1, Company1: $5000.01
Customer #2, Company2: $0
Customer #3, Company3: $150.25
Customer #4, Company4: $4000
Customer #5, Company5: $
--- Data with invalid orders deleted ---
Customer #1, Company1: $5000.01
Customer #3, Company3: $150.25
Customer #4, Company4: $4000 PL/SQL procedure successfully completed
-- Verify that the correct order details were stored
SELECT cust_name "Customer", amount "Valid order amount" FROM valid_orders;
SELECT cust_name "Customer", amount "Big order amount" FROM big_orders;
SELECT cust_name "Customer", amount "Rejected order amount" FROM rejected_orders;

5、使用%BULK_ROWCOUNT返回受影响的记录行数

CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS TABLE OF NUMBER;
depts NumList := NumList(30, 50, 60);
BEGIN
FORALL j IN depts.FIRST..depts.LAST
DELETE FROM emp_temp WHERE department_id = depts(j);
-- How many rows were affected by each DELETE statement?
FOR i IN depts.FIRST..depts.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Iteration #' || i || ' deleted ' ||
SQL%BULK_ROWCOUNT(i) || ' rows.');
END LOOP;
END;
/

6、FORALL与BULK COLLECT 一起使用(Using FORALL With BULK COLLECT)

CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS TABLE OF NUMBER;
depts NumList := NumList(10,20,30);
TYPE enum_t IS TABLE OF employees.employee_id%TYPE;
TYPE dept_t IS TABLE OF employees.department_id%TYPE;
e_ids enum_t;
d_ids dept_t;
BEGIN
FORALL j IN depts.FIRST..depts.LAST
DELETE FROM emp_temp WHERE department_id = depts(j)
RETURNING employee_id, department_id BULK COLLECT INTO e_ids, d_ids;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows:');
FOR i IN e_ids.FIRST .. e_ids.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Employee #' || e_ids(i) || ' from dept #' || d_ids(i));
END LOOP;
END;
/

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

Present   by   dylan.

ORACLE FORALL介绍的更多相关文章

  1. 【体系结构】Oracle参数介绍

    [体系结构]Oracle参数介绍 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩ ...

  2. Oracle asm介绍和安装linux+oracle10g+asm过程

    Oracle asm介绍和安装linux5.2+oracle10g+asm过程   1)ASM(自动存储管理)的来由:   ASM是Oracle 10g R2中为了简化Oracle数据库的管理而推出来 ...

  3. Oracle Dataguard 介绍

    Oracle DataGuard介绍 一. DataGuard的基本原理 当某次事务处理对生产数据库中的数据作出更改时,Oracle数据库将在一个联机重做日志文件里记录此次更改.在DataGuard中 ...

  4. [Oracle] Lob介绍

    [Oracle] Lob介绍   像Oracle这种关系型数据库,比较擅长处理结构化的数据,那么对于非结构化的数据,Oracle是怎么处理和存储的呢?Lob (Large Object)是Oracle ...

  5. oracle regexp_like介绍和例子

    oracle regexp_like介绍和例子 学习了:http://www.cnblogs.com/einyboy/archive/2012/08/01/2617606.html ORACLE中的支 ...

  6. Oracle forall bulk collect批量数据更新

    对于数据量较大的插入操作可采用此种方法操作,注意: limit减少内存占用,如果数据量较大一次性全部加载到内存中,对PGA来说压力太大,可采用limit的方法一次加载一定数量的数据,建议值通常为100 ...

  7. Oracle 备份与恢复介绍

    一.Oracle备份方式分类:Oracle有两类备份方式:(1)物理备份:是将实际组成数据库的操作系统文件从一处拷贝到另一处的备份过程,通常是从磁盘到磁带.物理备份又分为冷备份.热备份:   (2)逻 ...

  8. Oracle 存储过程介绍

    存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4 NULL; 5 END; 行1: CREATE OR REPLACE PROCEDURE ...

  9. ORACLE RMAN介绍

    本地连接: $ rman target /  or $ rman target / nocatalog 远程连接: $ rman target sys/sys@sky RMAN命令执行方式: 1.单条 ...

  10. oracle 序列介绍

    序列介绍 序列是一个计数器,它并不会与特定的表关联.通过创建Oracle序列和触发器实现表的主键自增. 序列的用途一般用来填充主键和计数. 序列使用 1.创建序列 ORACLE序列的语法格式为: CR ...

随机推荐

  1. Java开发者的Python快速进修指南:探索15种独特的Python特殊方法

    概述 在Python中,特殊方法(也称为魔术方法)是由Python解释器自动调用的,我们不需要手动调用它们,而是使用内置函数来间接地使用它们.举个例子,我们可以实现特殊方法__len__(),然后通过 ...

  2. 【特别的骚气】asp.net core运行时注入服务,实现类库热插拔

    引言 很久之前在群里有看到说asp.net core能不能在运行时注入程序,当时并没有太在意,刚才在某个群里又看到有人再问,core能不能在运行时注入服务,闲来无事,我就研究了一下,其实也比较简单,在 ...

  3. [转帖]fullgc问题解决:Full GC (Metadata GC Threshold)

    #问题描述 在工作过程中,遇到一个问题:Tomcat在重启或者发布的时候,会有多次的full GC. 笔者使用的版本说明: Tomcat7.0.25 JDK8 首先排查JVM的问题,就要把GC日志打开 ...

  4. [转帖]故障分析 | 让top命令直接显示Java线程名?-- 解析OpenJDK的一个bug修复

    https://zhuanlan.zhihu.com/p/413136873 作者:阎虎青DBLE 开源项目负责人,负责分布式数据库中间件研发工作:持续专注于数据库方面的技术,始终在一线从事开发:对数 ...

  5. [转帖]jmap执行失败了,怎么获取heapdump?

    https://www.jianshu.com/p/f4bfd169b4ca   在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题. 但当我反复模拟OOM场景 ...

  6. [转帖]Linux块层技术全面剖析-v0.1

    Linux块层技术全面剖析-v0.1 perftrace@gmail.com 前言 网络上很多文章对块层的描述散乱在各个站点,而一些经典书籍由于更新不及时难免更不上最新的代码,例如关于块层的多队列.那 ...

  7. 国产飞腾2000+服务器 存储单盘性能简单验证 SSD 与 HDD

    有kylinV10的源 可以直接安装fio yum install fio -y 第一步, 将sdd 进行初始化,并且设置文件系统 fdisk /dev/sdbmkdir /ssd2 mkfs.ext ...

  8. firewall-cmd 命令简单总结

    最近进行相关网络设置, 发现需要总结一下不然总是会忘记. # 1. 开放IP地址访问 firewall-cmd --zone=trusted --add-source=yourip --permane ...

  9. 【OpenAI】ChatGPT函数调用(Function Calling)实践

    6月13日OpenAI在Chat Completions API中添加了新的函数调用(Function Calling)能力,帮助开发者通过API方式实现类似于ChatGPT插件的数据交互能力. 本文 ...

  10. vite引入图片

    vite引入图片出现的问题 -不能够页面 <template> <div> <div> <img class="imgsize" sr=& ...