oracleplsqltoaddatabase-cursorora-00932

ORA-00932: inconsistent datatypes: expected - got -


I have been using Oracle(10g.2) as a PHP programmer for almost 3 years, but when I gave an assignment, I have tried to use the ref cursors and collection types for the first time. And I 've searched the web, when I faced with problems, and this ora-00932 error really overwhelmed me. I need help from an old hand.

Here is what I've been tackling with, I want to select rows from a table and put them in a ref cursor, and then with using record type, gather them within an associative array. And again from this associative array, make a ref cursor. Don't ask me why, I am writing such a complicated code, because I need it for more complex assignment. I might be sound confusing to you, thus let me show you my codes.

I have 2 types defined under the types tab in Toad. One of them is an object type:

CREATE OR REPLACE
TYPE R_TYPE AS OBJECT(sqn number,firstname VARCHAR2(30), lastname VARCHAR2(30));

Other one is collection type which is using the object type created above:

CREATE OR REPLACE
TYPE tr_type AS TABLE OF r_type;

Then I create a package:

CREATE OR REPLACE PACKAGE MYPACK_PKG IS
TYPE MY_REF_CURSOR IS REF CURSOR;
PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR);
END MYPACK_PKG;

Package Body:

CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
 PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
  rcur MYPACK_PKG.MY_REF_CURSOR;
  sql_stmt VARCHAR2(1000);
  l_rarray   tr_type := tr_type();
                l_rec r_type;

 BEGIN
     sql_stmt :=  'SELECT 1,e.first_name,e.last_name  FROM hr.employees e ';
     OPEN rcur FOR sql_stmt;
     LOOP
       fetch rcur into l_rec;
                  exit when rcur%notfound;
     l_rarray := tr_type( l_rec );
     END LOOP;
   CLOSE rcur;
    --OPEN r_cursor FOR SELECT * FROM TABLE(cast(l_rarray as tr_type) );


END MY_PROC;
END MYPACK_PKG;

I commented out the last line where I open ref cursor. Because it's causing another error when I run the procedure in Toad's SQL Editor, and it is the second question that I will ask. And lastly I run the code in Toad:

variable r refcursor
declare
r_out MYPACK_PKG.MY_REF_CURSOR;
begin
MYPACK_PKG.MY_PROC(r_out);
:r := r_out;
end;
print :r

There I get the ora-00932 error.


Solution

  • The way you are using the REF CURSOR is uncommon. This would be the standard way of using them:

    SQL> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
      2     PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
      3     BEGIN
      4        OPEN r_cursor FOR SELECT e.empno,e.ENAME,null  FROM scott.emp e;
      5     END MY_PROC;
      6  END MYPACK_PKG;
      7  /
    
    Corps de package crÚÚ.
    
    SQL> VARIABLE r REFCURSOR
    SQL> BEGIN
      2     MYPACK_PKG.MY_PROC(:r);
      3  END;
      4  /
    
    ProcÚdure PL/SQL terminÚe avec succÞs.
    
    SQL> PRINT :r
    
         EMPNO ENAME      N
    ---------- ---------- -
          7369 SMITH
          7499 ALLEN
          7521 WARD
          7566 JONES
          7654 MARTIN
          [...]
    
    14 ligne(s) sÚlectionnÚe(s).
    

    I'm not sure what you are trying to accomplish here, you're fetching the ref cursor inside the procedure and then returning another ref cursor that will have the same data. I don't think it's necessary to fetch the cursor at all in the procedure. Let the calling app do the fetching (here the fetching is done by the print).

    Update: why are you getting the unhelpful error message?

    You're using a cursor opened dynamically and I think that's part of the reason you are getting the unhelpful error message. If we use fixed SQL the error message is different:

    SQL> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
      2     PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
      3        TYPE type_rec IS RECORD (qn number,
      4                                 firstname VARCHAR2(30),
      5                                 lastname VARCHAR2(30));
      6        lt_record type_rec; /* Record type */
      7        lt_object r_type; /* SQL Object type */
      8     BEGIN
      9        OPEN r_cursor FOR SELECT e.empno,e.ENAME,null  FROM scott.emp e;
     10        FETCH r_cursor INTO lt_record; /* This will work */
     11        FETCH r_cursor INTO lt_object; /* This won't work in 10.2 */
     12     END MY_PROC;
     13  END MYPACK_PKG;
     14  /
    
    Package body created
    
    SQL> VARIABLE r REFCURSOR
    SQL> BEGIN
      2     MYPACK_PKG.MY_PROC(:r);
      3  END;
      4  /
    BEGIN
    *
    ERREUR Ó la ligne 1 :
    ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
    ORA-06512: at "APPS.MYPACK_PKG", line 11
    ORA-06512: at line 2
    

    I outlined that currently in 10.2 you can fetch a cursor into a PLSQL record but not in a SQL Object.

    Update: regarding the PLS-00306: wrong number or types of arguments

    l_rarray is a NESTED TABLE, it needs to be initialized and then extended to be able to store elements. For example:

    SQL> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
      2     PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
      3        lr_array tr_type := tr_type(); /* SQL Array */
      4     BEGIN
      5        FOR cc IN (SELECT e.empno, e.ENAME, NULL lastname
      6                     FROM scott.emp e) LOOP
      7           lr_array.extend;
      8           lr_array(lr_array.count) := r_type(cc.empno,
      9                                              cc.ename,
     10                                              cc.lastname);
     11           /* Here you can do additional procedural work on lr_array */
     12        END LOOP;
     13        /* then return the result set */
     14        OPEN r_cursor FOR SELECT * FROM TABLE (lr_array);
     15     END MY_PROC;
     16  END MYPACK_PKG;
     17  /
    
    Corps de package crÚÚ.
    
    SQL> print r
    
           SQN FIRSTNAME                      LASTNAME
    ---------- ------------------------------ -----------
          7369 SMITH                          
          7499 ALLEN                          
          7521 WARD                           
          [...]
    
    14 ligne(s) sÚlectionnÚe(s).
    

    For further reading you can browse the documentation for PL/SQL collections and records.