Skip to main content

PLS-00436 Restriction in FORALL Statements Removed From 11g

The PLS-00436 restriction has been removed from 11g, and now we can reference each element of the collection object when used with FORALL statement.Each element can now be referenced using SET and WHERE clauses of a DML statement in a FORALL construct.

Sample program :


conn scott/tiger
create table demo_plsql_436 as select * from emp where 1=2;


/* The procedure "display_demo_plsql_436" will display the data of  table demo_plsql_436 */

create or replace procedure display_demo_plsql_436 as
   cursor c1 is select ename, sal from demo_plsql_436;
   emp_name demo_plsql_436.ename%type;
   emp_sal  demo_plsql_436.sal%type;
begin
   open c1;
   loop
      fetch c1 into emp_name, emp_sal;
   exit when c1%notfound;
   dbms_output.put_line(rpad (emp_name,10,' ')|| '     ' || rpad(emp_sal,7,' '));
   end loop;
   close c1;
end display_demo_plsql_436;
/


/* The below given sample code will demonstrate the enhancement of removing the  restriction PLS-00436 while using FORALL  with DML*/


set serveroutput on
declare
  type empcol_t is table of emp%rowtype index by pls_integer;
  empcol empcol_t;
begin
  select * bulk collect into empcol from emp;

/*Case #1 :Inserting the data referencing individual elements for the collection using FORALL*/

  forall i in empcol.first..4
    insert into demo_plsql_436 (empno, ename, sal)
      values (empcol(i).empno, empcol(i).ename, empcol(i).sal);
   dbms_output.put_line('=====Data Inserted without error==========');
     display_demo_plsql_436;
 
/*Case #2 : Update rows where some key value (empno in this case) matches the key value in the record bind into the bulk DML operation.*/

  for i in empcol.first..4 loop
    empcol(i).sal := empcol(i).sal * 1.1;
  end loop;
  dbms_output.put_line('Salary updated in Nested table');
 
forall i in empcol.first..4
    update demo_plsql_436 set row = empcol(i)
      where empno = empcol(i).empno;
dbms_output.put_line('=====Salary updated without error==========');
     display_demo_plsql_436;
 
/*Case #3 : Update a subset of columns in the SET clause with values from the record in bind into the bulk DML operation*/
  
  for i in empcol.first..4 loop
    empcol(i).sal := empcol(i).sal * 1.5;
  end loop;
 
forall i in empcol.first..4
    update demo_plsql_436 set (sal) = empcol(i).sal
      where empno = empcol(i).empno;
dbms_output.put_line('=====Revised salary updated without error==========');
     display_demo_plsql_436;
end;
/

Sample Output:


=====Data Inserted without error==========
SMITH          800
ALLEN          1600
WARD           1250
JONES          2975
Salary updated in Nested table
=====Salary updated without error==========
SMITH          880
ALLEN          1760
WARD           1375
JONES          3272.5
=====Revised salary updated without error==========
SMITH          1320
ALLEN          2640
WARD           2062.5
JONES          4908.75


The Restriction still hold good when referencing each element of the collect with returning clause.But now from 11g onwards we get a new error.

PLS-437: FORALL bulk index cannot be used in RETURNING clause.

Sample Code to demonstrate the restriction :

SQL> declare
  2    type empcol_t is table of emp%rowtype index by pls_integer;
  3    empcol empcol_t;
  4  begin
  5    select * bulk collect into empcol from emp;
  6
  7    forall i in empcol.first..empcol.last
  8      update emp set row = empcol(i)
  9        where empno = empcol(i).empno
 10        returning sal bulk collect into empcol(i).sal;
 11
 12  end;
 13  /
      returning sal bulk collect into empcol(i).sal;
                                      *
ERROR at line 10:
ORA-06550: line 10, column 39:
PLS-00437: FORALL bulk index cannot be used in RETURNING clause
ORA-06550: line 10, column 52:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 8, column 5:
PL/SQL: SQL Statement ignored

Error Message in 10g

ERROR at line 9:
ORA-06550: line 9, column 21:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND
table of records

ORA-06550: line 9, column 21:
PLS-00382: expression is of wrong type
ORA-06550: line 10, column 39:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND
table of records

ORA-06550: line 10, column 52:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 8, column 5:
PL/SQL: SQL Statement ignored

Comments

Popular posts from this blog

Check Whether File Exists on the Server Using PLSQL

There are different packages using which you can check whether a file exists on the database / application server. The different ways are 1. Using UTL_HTTP from Web Server 2. Using UTL_FILE from Database Server 3. Using DBMS_LOB from Database Server 1. You can also use UTL_HTTP package to check whether a file exists on a web server from the database. SET SERVEROUTPUT ON DECLARE   url       VARCHAR2(256) := 'http://www.oracle.com/index1.html';   username  VARCHAR2(256);   password  VARCHAR2(256);   req       UTL_HTTP.REQ;   resp      UTL_HTTP.RESP; BEGIN   req := UTL_HTTP.BEGIN_REQUEST(url);   IF (username IS NOT NULL) THEN     UTL_HTTP.SET_AUTHENTICATION(req, username, password);   END IF;   resp := UTL_HTTP.GET_RESPONSE(req);   DBMS_OUTPUT.PUT_LINE('response -->' || resp.status_code); END; / If the f...

11.2 PLSQL New Feature : How to use DBMS_PARALLEL_EXECUTE to Update Large Tables in Parallel

The DBMS_PARALLEL_EXECUTE package enables you to incrementally update the data in a large table in parallel, in two high-level steps: 1. Group sets of rows in the table into smaller chunks. 2. Apply the desired UPDATE statement to the chunks in parallel, committing each time you have finished processing a chunk. This technique is recommended whenever you are updating a lot of data. Its advantages are: o You lock only one set of rows at a time, for a relatively short time, instead of locking the entire table. o You do not lose work that has been done if something fails before the entire operation finishes. o You reduce rollback space consumption. o You improve performance Different Ways to Spilt Workload : 1. CREATE_CHUNKS_BY_NUMBER_COL: Chunks the table associated with the given task by the specified column. 2. CREATE_CHUNKS_BY_ROWID : Chunks the table associated with the given task by ROWID 3. CREATE_CHUNKS_BY_SQL : Chunks the table associated with the given task by me...

PRAGMA AUTONOMOUS_TRANSACTION with Transaction Isolation

What is PRAGMA ? PRAGMA is a language construct that specifies how a compiler (or assembler or interpreter) should process its input. PRAGMA keyword in PLSQL is used to direct compiler to work differently when compared to the normal code. Pragmas are processed at compile time, not at run time. What is AUTONOMOUS_TRANSACTION ? The AUTONOMOUS_TRANSACTION pragma changes the way a subprogram works within a transaction. A subprogram marked with this pragma can do SQL operations and commit or roll back those operations, without committing or rolling back the data in the main transaction. The statement clearly states that autonomous transaction executes independent of main transaction. The concept was crystal clear to me and I had used it extensively in designing some of the solution. Very recently a question raised in my mind. Will the changes made by autonomous transaction be visible in the main transaction ?  I didn't have an answer and hence tried to do a research. L...