Quantcast
OracleBrains.Com header image 2

PL/SQL::Improvement in BULK In-BIND table of records

September 27th, 2007 by Anand · 5 Comments

Previous 11g, if i want to refer the field of a ‘Table Of record’ with in FORALL, Oracle raises error as follows

PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records

Example:

SCOTT>SELECT banner
2  FROM v$version;

BANNER
—————————————————————-
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SCOTT>DECLARE
2   TYPE s_tab IS TABLE OF emp%ROWTYPE;
3   s_array s_tab;
4  BEGIN
5   SELECT * BULK COLLECT
6   INTO s_array
7   FROM EMP
8   WHERE comm IS NULL;
9
10   FORALL i IN 1..s_array.COUNT
11   UPDATE emp
12   SET sal = 50000
13   WHERE empno = s_array(i).empno;
14  END;
15  /
WHERE empno = s_array(i).empno;
*
ERROR at line 13:
ORA-06550: line 13, column 16:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
ORA-06550: line 13, column 16:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 16:
PL/SQL: ORA-22806: not an object or REF
ORA-06550: line 11, column 2:
PL/SQL: SQL Statement ignored

Now check out Oracle 11g

SCOTT>SELECT banner
2  FROM v$version;

BANNER
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE    11.1.0.6.0      Production
TNS for Linux: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SCOTT>SELECT * FROM emp WHERE comm IS NULL;

EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
———- ———- ——— ———- ——— ———- ———- ———-
7369 SMITH      CLERK           7902 17-DEC-80        800                    20
7566 JONES      MANAGER         7839 02-APR-81       2975                    20
7698 BLAKE      MANAGER         7839 01-MAY-81       2850                    30
7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
7839 KING       PRESIDENT            17-NOV-81       5000                    10
7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
7900 JAMES      CLERK           7698 03-DEC-81        950                    30
7902 FORD       ANALYST         7566 03-DEC-81       3000                    20
7934 MILLER     CLERK           7782 23-JAN-82       1300                    10

10 rows selected.

SCOTT>DECLARE
2   TYPE s_tab IS TABLE OF emp%ROWTYPE;
3   s_array s_tab;
4  BEGIN
5   SELECT * BULK COLLECT
6   INTO s_array
7   FROM EMP
8   WHERE comm IS NULL;
9
10   FORALL i IN 1..s_array.COUNT
11   UPDATE emp
12   SET sal = 50000
13   WHERE empno = s_array(i).empno;
14  END;
15  /

PL/SQL procedure successfully completed.

SCOTT>SELECT * FROM emp WHERE comm IS NULL;

EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
———- ———- ——— ———- ——— ———- ———- ———-
7369 SMITH      CLERK           7902 17-DEC-80      50000                    20
7566 JONES      MANAGER         7839 02-APR-81      50000                    20
7698 BLAKE      MANAGER         7839 01-MAY-81      50000                    30
7782 CLARK      MANAGER         7839 09-JUN-81      50000                    10
7788 SCOTT      ANALYST         7566 19-APR-87      50000                    20
7839 KING       PRESIDENT            17-NOV-81      50000                    10
7876 ADAMS      CLERK           7788 23-MAY-87      50000                    20
7900 JAMES      CLERK           7698 03-DEC-81      50000                    30
7902 FORD       ANALYST         7566 03-DEC-81      50000                    20
7934 MILLER     CLERK           7782 23-JAN-82      50000                    10

10 rows selected.


Tags: Oracle 11g New Features

5 responses so far ↓

  • 1 Veeresh // Nov 23, 2007 at 4:35 pm

    The BULK method of selecting records may take more time in a Clustered Data Base Systems(Spreaded database over multiple hard drives). I tried this method, I did not get expected results, rather It has taken more time than pure SQL method of reading bulk records. This method would work in a database mounted in a single hard drive.

  • 2 Ray DeBruyn // Dec 6, 2007 at 5:37 am

    There are no expected results posted here, so you must have an assumed or expected result. I don’t really see how bulk binding can be slower. I’d be interested to see exactly what code you ran, what your expectation was and what result you had.

  • 3 Rajender Singh // Dec 14, 2007 at 12:05 am

    Hi Veeresh,

    I am also wondering why you didn’t get expected results.

    Logically running whole thing as one SQL is always faster than running more than one SQL to achive same thing.

    Regards,

    Raj

  • 4 Brijesh // Apr 8, 2008 at 3:01 pm

    If this bulk bind solution in oracel 11g then how can we solve that type of problem in oracle 8i versrion

  • 5 Rajender Singh // Apr 8, 2008 at 11:35 pm

    Hi Brijesh,

    Before 11g, I could find only following way to achieve the above solution due to restriction before 11g.

    DECLARE
    TYPE empRec IS RECORD
    (
    empno DBMS_SQL.NUMBER_TABLE,
    ename DBMS_SQL.VARCHAR2_TABLE,
    job DBMS_SQL.VARCHAR2_TABLE,
    mgr DBMS_SQL.NUMBER_TABLE,
    hiredate DBMS_SQL.DATE_TABLE,
    sal DBMS_SQL.NUMBER_TABLE,
    comm DBMS_SQL.NUMBER_TABLE,
    deptno DBMS_SQL.NUMBER_TABLE
    );

    l_record empRec;
    BEGIN
    SELECT * BULK COLLECT
    INTO l_record.empno, l_record.ename, l_record.job, l_record.mgr, l_record.hiredate, l_record.sal, l_record.comm, l_record.deptno
    FROM EMP
    WHERE comm IS NULL;

    FORALL I IN 1 .. l_record.empno.count
    UPDATE emp
    set empno = l_record.empno(i),
    ename = l_record.ename(i),
    job = l_record.job(i),
    mgr = l_record.mgr(i),
    hiredate = l_record.hiredate(i),
    sal = l_record.sal(i),
    comm = l_record.comm(i),
    deptno = l_record.deptno(i)
    WHERE empno = l_record.empno(i);

    END;

    There is very nice discussion about this kind of problem at Ask Tom.

    Check out following url:
    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2367352052686

    Thanks & Regards,

    Raj

Leave a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

Comment moderation is enabled. Your comment may take some time to appear.