本文介绍如何使用FORALL语法。

基本概念

通过将要用于重复执行 DELETE、INSERT 或 UPDATE 命令的所有值一次性传递给数据库服务器(而不是使用新值反复调用 DML 命令),集合可用于更有效地处理 DML 命令。以此类方式处理的 DML 命令将使用 FORALL 语句指定。此外,DML 命令中还给出一个或多个集合,每次执行命令时都要替换这些集合的不同值。

FORALL index IN lower_bound .. upper_bound
  { insert_stmt | update_stmt | delete_stmt };

index 是在 insert_stmt、update_stmt 或 delete_stmt DML 命令中给出的集合中的位置,它从 lower_bound 给出的整数值向上迭代到 upper_bound(含上限)。

说明 如果在 FORALL 语句的任何迭代期间发生异常,则自开始执行 FORALL 语句以来执行的所有更新都将自动回滚。此行为与 Oracle 数据库不兼容。Oracle 允许显式使用 COMMIT 或 ROLLBACK 命令来控制是提交还是回滚发生异常之前执行的更新。

示例

FORALL 语句创建一个循环:该循环的每次迭代都会递增 index 变量(通常在该循环内使用 index 选择集合的成员)。迭代次数由 lower_bound .. upper_bound 子句进行控制。该循环为 lower_bound 和 upper_bound(含上限)之间的每个整数执行一次,并且每次迭代会使索引按 1 递增。例如:

FORALL i IN 2 .. 5

创建一个执行四次的循环:在第一次迭代中,index (i) 设置为值 2;在第二次迭代中,索引设置为值 3,依此类推。该循环执行到值 5,然后终止。

以下示例创建一个表 emp_copy,该表是 emp 表的空副本。该示例声明一个作为数组的类型 emp_tbl,数组中的每个元素都是复合类型,由用于创建表 emp 的列定义组成。该示例还在 emp_tbl 类型中创建了索引。

t_emp 是类型 emp_tbl 的关联数组。SELECT 语句使用 BULK COLLECT INTO 命令填充 t_emp 数组。在填充 t_emp 后,FORALL 语句会遍历 t_emp 数组索引中的值 i,然后将每个记录行插入 emp_copy 中。

CREATE TABLE emp_copy(LIKE emp);

DECLARE

    TYPE emp_tbl IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;

    t_emp emp_tbl;

BEGIN
    SELECT * FROM emp BULK COLLECT INTO t_emp;

    FORALL i IN t_emp.FIRST .. t_emp.LAST
     INSERT INTO emp_copy VALUES t_emp(i);

END;

以下示例使用 FORALL 语句更新三名员工的工资:

DECLARE
    TYPE empno_tbl  IS TABLE OF emp.empno%TYPE INDEX BY BINARY_INTEGER;
    TYPE sal_tbl    IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
    t_empno         EMPNO_TBL;
    t_sal           SAL_TBL;
BEGIN
    t_empno(1)  := 9001;
    t_sal(1)    := 3350.00;
    t_empno(2)  := 9002;
    t_sal(2)    := 2000.00;
    t_empno(3)  := 9003;
    t_sal(3)    := 4100.00;
    FORALL i IN t_empno.FIRST..t_empno.LAST
        UPDATE emp SET sal = t_sal(i) WHERE empno = t_empno(i);
END;

SELECT * FROM emp WHERE empno > 9000;

 empno | ename  |   job   | mgr | hiredate |   sal   | comm | deptno
-------+--------+---------+-----+----------+---------+------+--------
  9001 | JONES  | ANALYST |     |          | 3350.00 |      |     40
  9002 | LARSEN | CLERK   |     |          | 2000.00 |      |     40
  9003 | WILSON | MANAGER |     |          | 4100.00 |      |     40
(3 rows)

以下示例通过 FORALL 语句删除三名员工。

DECLARE
    TYPE empno_tbl  IS TABLE OF emp.empno%TYPE INDEX BY BINARY_INTEGER;
    t_empno         EMPNO_TBL;
BEGIN
    t_empno(1)  := 9001;
    t_empno(2)  := 9002;
    t_empno(3)  := 9003;
    FORALL i IN t_empno.FIRST..t_empno.LAST
        DELETE FROM emp WHERE empno = t_empno(i);
END;

SELECT * FROM emp WHERE empno > 9000;

 empno | ename | job | mgr | hiredate | sal | comm | deptno
-------+-------+-----+-----+----------+-----+------+--------
(0 rows)