tags:

views:

1342

answers:

3

Using Oracle 10g PL/SQL. I'm trying to find a way to pass a custom defined RECORD type around without the procedures having to know its real type. Sounds like a job for SYS.ANYDATA but it doesn't look like Oracle supports wrapping RECORD types. For example:

DECLARE
  TYPE t_rec IS RECORD (id number);
  v_rec t_rec;
  v_ad SYS.ANYDATA;
BEGIN
  v_rec.id := 1;
  v_ad := SYS.ANYDATA.CONVERTOBJECT(v_rec);
END;

Fails with error:

v_ad := SYS.ANYDATA.CONVERTOBJECT(v_rec);
      *
ERROR at line 7:
ORA-06550: line 7, column 11:
PLS-00306: wrong number or types of arguments in call to 'CONVERTOBJECT'
ORA-06550: line 7, column 3:
PL/SQL: Statement ignored

Clearly convertobject is not expecting a RECORD but I don't see any other candidates on http://download-west.oracle.com/docs/cd/B19306_01/appdev.102/b14258/t_anydat.htm either.

Ultimately what I'm looking for is some way to store different RECORD types in the same variable. I'd also like to avoid Oracle object types (top-level types defined outside of packages) as they have their own issues.

Thanks.

+1  A: 

This section of the PL/SQL User's Guide and Reference would indicate that you cannot do what you want to do here directly - PL/SQL wants to try to convert parameters at runtime. You might want to see if you can make a REFCURSOR work. Simple example:

CREATE OR REPLACE PROCEDURE TheTest AS

    v_cursor SYS_REFCURSOR;
    v_v1   NUMBER;
    v_v2   NUMBER;
    v_v3   NUMBER;

  PROCEDURE getRS(pr OUT SYS_REFCURSOR) IS
  BEGIN
    OPEN pr FOR SELECT 1,2,3 FROM dual;
  END;

  BEGIN
    getRS(v_cursor);
    FETCH v_cursor INTO v_v1, v_v2, v_v3;
    dbms_output.put_line(v_v1||','||v_v2||','||v_v3);
    CLOSE v_cursor;
  END;

You can then pass around the cursor variable reference to your heart's content.

HTH.

EDIT:

Another option, depending on how many record types you need to deal with, is to overload the same handler procedure(s) with the various record types.

DCookie
Thanks DCookie. I'm using the RECORD type not to store and pass a record from a cursor but as a structure to define several properties that can be passed around. Is it possible to store a programmer-defined RECORD type in a SYS_REFCURSOR?
jlpp
No, you need a cursor, which is why I gave the example I did. It's fudging the system a bit by selecting your single record values from dual and passing the resulting cursor around.
DCookie
+1  A: 

You are trying to deal with two separate layers, PL/SQL and SQL. SQL does not understand PL/SQL records and will not deal with them.

"Ultimately what I'm looking for is some way to store different RECORD types in the same variable" Write wrappers that convert them to/from XML.

No offence intended, but looking at your other posts, you seem to be trying to impose an object oriented paradigm on SQL and PL/SQL, and it isn't fitting too well. If you are not coding for XE, then maybe consider using Java Stored Procedures in the database.

Gary
Thanks Gary. Are you saying that SYS.ANYDATA is SQL and the RECORD type is PL/SQL?Regarding XML, that's an idea. I don't know that I can use that approach though because it would involve converting to and from XML more than once as the variable is passed around.No offense taken. You're right. I'm trying to squeeze as much OO out of Oracle as I can. I briefly looked into Java procs but it looked like it would suffer from the same constraint: parameters in/out of the Java proc are ultimately Oracle data types... right?
jlpp
Correct in regards record types being PL/SQL. You would pass SQL types to Java. But I guess (not being a Java person) once you are in the Java layer, you can pass java objects between java modules/classes.
Gary
A: 

From my point of view application design should start in the most bottom layer, which usually is the database. You seem to try to force the DB do something it is not meant for.

If you really want universal container then you always can serialize anything as for example xml and store it as text (clob) (in this case you can store it as xmltype). However I would suggest to rethink the approach and start using the core capabilities of the DB - store and retrieve rows.

Michal Pravda
Thanks Michal. See my comment to Gary.
jlpp