本文介绍如何使用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 语句创建一个循环:该循环的每次迭代都会递增 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)