xmloracleoracle10gextractora-00997

How to extract data from a LONG column holding XML strings


Here is my table

MYTABLE(ID NUMBER(10),
        DATATYPE VARCHAR2(2 BYTE),
        XMLDATA LONG
)

Note1: I cannot alter this table Note2: I'm using Oracle 10g

Here is a sample of XMLDATA

<myxml version="1">
  <node1>
   <child1>value to get</child1>
  </node1>
</myxml>

I tried xmltype() but it's not working with a LONG type (ORA-00997 illegal use of LONG type). Maybe I should copy XMLDATA values to a new table and convert to a CLOB then I can convert to xmltype and use EXTRACTVALUE()?

What is the best way to extract 'value to get' ?


Solution

  • Following is some code that is supposed to output a CLOB from a LONG of arbitrary length. It dumps the body of MY_TRIGGER to dbms_output. If it works you should be able to parse that as needed.

    DECLARE
        c_chunk_limit CONSTANT   INTEGER := 100;
    
        v_cur                    INTEGER := DBMS_SQL.open_cursor;
        v_offset                 INTEGER;
        v_chunk                  VARCHAR2(32767);
        v_chunk_size             INTEGER;
    BEGIN
        DBMS_SQL.parse(
            v_cur,
            'SELECT trigger_body FROM dba_triggers WHERE trigger_name = ''MY_TRIGGER''',
            DBMS_SQL.native
        );
    
        DBMS_SQL.define_column_long(v_cur, 1);  -- 1 here represents the column position in the select list the long is column#1
    
        IF DBMS_SQL.execute_and_fetch(v_cur) > 0
        THEN
            v_offset   := 0;
    
            LOOP
                DBMS_SQL.column_value_long(
                    v_cur,
                    1,  -- 1 here represents the column position in the select list the long is column#1
                    c_chunk_limit,
                    v_offset,
                    v_chunk,
                    v_chunk_size
                );
    
                EXIT WHEN v_chunk_size = 0;
    
                v_offset   := v_offset + v_chunk_size;
                DBMS_OUTPUT.put_line(v_chunk);
            END LOOP;
        END IF;
    
        DBMS_SQL.close_cursor(v_cur);
    END;
    /