Object Type and XML equivalency in Oracle
Tags: Xml, Sql, Plsql, Oracle, Database Development

Most oracle developers don’t use object types…and there’s good reasons for that — it’s a somewhat half-baked OO implementation that is unlikely to impress OO fans, and it doesn’t give you a whole lot more than just working with tables for the database minded. But there are some novel things that you can do with them when combined with another largely unused feature of Oracle — XML.

Let’s start with an object type definition:

CREATE OR REPLACE TYPE typ_person force AS OBJECT

(

phone_number VARCHAR2(100)

,first_name VARCHAR2(255)

,last_name VARCHAR2(255)

,CONSTRUCTOR FUNCTION typ_person RETURN SELF AS RESULT

);

/ CREATE OR REPLACE TYPE BODY typ_person IS

--This is just a helper function so we can easily build an instance

CONSTRUCTOR FUNCTION typ_person RETURN SELF AS RESULT IS

BEGIN

RETURN;

END typ_person;

END;

/

Interesting thing number 1 an object can be converted to xml by passing it to the xmltype constructor:

DECLARE

p typ_person;

v_xmltype xmltype;

BEGIN

p := typ_person(

phone_number => '555-555-5555'

,first_name => 'Joe'

,last_name => 'Smith');

v_xmltype := xmltype(p);

dbms_output.put_line(v_xmltype.getstringval());

END;

This outputs:

<TYP_PERSON>

<PHONE_NUMBER>555-555-5555</PHONE_NUMBER>

<FIRST_NAME>Joe</FIRST_NAME>

<LAST_NAME>Smith</LAST_NAME>

</TYP_PERSON>

Interesting thing number 2, it’s built in to go the other way as well (creating an object from an xmltype):

DECLARE

p typ_person;

v_xmltype xmltype;

v_ref_cursor SYS_REFCURSOR;

BEGIN

OPEN v_ref_cursor FOR

SELECT '555-555-5555' phone_number

,'Joe' first_name

,'Smith' last_name

FROM dual;

v_xmltype := xmltype(v_ref_cursor);

CLOSE v_ref_cursor;

v_xmltype.extract('/ROWSET/ROW').toobject(p);

dbms_output.put_line('My Name is ' || p.first_name

|| ' '

|| p.last_name); END;

Which will output “My Name is Joe Smith”. Interestingly the XML to type conversion instantiated our object. Basically it did a lot of heavy lifting for us by instantiating the object and setting all of the instance attributes to those in the XMLType.

We had to finesse the XML output a little by extracting only the parts that had to do with the object type. By default when oracle creates an XMLtype it surrounds it all with <ROWSET><ROW>each row</ROW></ROWSET>

Our type doesn’t know anything about this ROWSET business but can infer that a record type is delineated the same way as a row. You can view the ROWSET as a collection and the ROW as singular instances of the collection — in this case our single type. So we strip off the ROWSET and give it what it does know.

To make this a little more concrete, the conversion of the ref cursor to an xmltype is this:

<ROWSET>

<ROW>

<PHONE_NUMBER>555-555-5555</PHONE_NUMBER>

<FIRST_NAME>Joe</FIRST_NAME>

<LAST_NAME>Smith</LAST_NAME>

</ROW>

</ROWSET>

After the extract call you’re left with:

<ROW>

<PHONE_NUMBER>555-555-5555</PHONE_NUMBER>

<FIRST_NAME>Joe</FIRST_NAME>

<LAST_NAME>Smith</LAST_NAME>

</ROW>

At this level (a single row, or instance) the built in Oracle XML machinery can convert this to an object type. It’s actually quite powerful. In the next post I will build on this example and construct a generic DML interface for any object type using this XML/Type equivalency.