EnterpriseDB

Previous PageTable Of ContentsNext Page

4.9.3 Using the FORALL Statement

Collections can be used to more efficiently process DML commands by passing all the values to be used for repetitive execution of a DELETE, INSERT, or UPDATE command in one pass to the database server rather than re-iteratively invoking the DML command with new values. The DML command to be processed in such a manner is specifed with the FORALL statement. In addition, one or more collections are given in the DML command where different values are to be substituted each time the command is executed.

FORALL index IN lower_bound .. upper_bound
  { insert | update | delete };

index is the position in the collection given in the insert, update, or delete DML command that iterates from the integer value given as lower_bound up to and including upper_bound.

Note: If an exception occurs during any iteration of the FORALL statement, all updates that occurred since the start of the execution of the FORALL statement are automatically rolled back. This behavior is not Oracle compatible. Oracle allows explicit use of the COMMIT or ROLLBACK commands to control whether or not to commit or roll back updates that occurred prior to the exception.

The following example uses an INSERT command with the FORALL statement to insert three new employees into the emp table.

DECLARE
    TYPE empno_tbl  IS TABLE OF emp.empno%TYPE INDEX BY BINARY_INTEGER;
    TYPE ename_tbl  IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
    TYPE job_tbl    IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
    TYPE sal_tbl    IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
    TYPE deptno_tbl IS TABLE OF emp.deptno%TYPE INDEX BY BINARY_INTEGER;
    t_empno         EMPNO_TBL;
    t_ename         ENAME_TBL;
    t_job           JOB_TBL;
    t_sal           SAL_TBL;
    t_deptno        DEPTNO_TBL;
BEGIN
    t_empno(1)  := 9001;
    t_ename(1)  := 'JONES';
    t_job(1)    := 'ANALYST';
    t_sal(1)    := 3200.00;
    t_deptno(1) := 40;
    t_empno(2)  := 9002;
    t_ename(2)  := 'LARSEN';
    t_job(2)    := 'CLERK';
    t_sal(2)    := 1400.00;
    t_deptno(2) := 40;
    t_empno(3)  := 9003;
    t_ename(3)  := 'WILSON';
    t_job(3)    := 'MANAGER';
    t_sal(3)    := 4000.00;
    t_deptno(3) := 40;
    FORALL i IN t_empno.FIRST..t_empno.LAST
        INSERT INTO emp (empno,ename,job,sal,deptno)
            VALUES (t_empno(i),t_ename(i),t_job(i),t_sal(i),t_deptno(i));
END;

SELECT * FROM emp WHERE empno > 9000;

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

The following example updates the salary of these three employees in a FORALL statement.

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)

The final example deletes these three employees in a FORALL statement.

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)

Previous PageTable Of ContentsNext Page

Powered by Transit