1

I would like to import an XML file to Oracle SQL with SQL developer. The XML has more than one node, my XML structure:

<"<"SPECTRAEXCHANGE>">"
<"<"APPLICATION>">"
<"<"SV_SV_ID>">"kClong<"<"/SV_SV_ID/>">"
<"<"SS_SS_ID>">"kClong<"<"/SS_SS_ID/>">"
<"<"AP_NAME>">"kCstring (64)<"<"/AP_NAME/>">"
<"<"AP_PRJ_IDENT>">"kCstring (32)<"<"/AP_PRJ_IDENT/>">"
<"<"STATION>">"
<"<"TCS_NAME>">"kCstring (64)<"<"/TCS_NAME/>">"
<"<"TCS_CALL>">"kCstring (256)<"<"/TCS_CALL/>">"
<"<"HORIZONTAL_ELEVATIONS>">"
<"<"HORIZONTAL_ELEVATION>">"
<"<"HE_AZIMUT>">"kCdouble<"<"/HE_AZIMUT/>">"
<"<"HE_ELEVATION>">"kCdouble<"<"/HE_ELEVATION/>">"
<"<"/HORIZONTAL_ELEVATION/>">"
<"<"/HORIZONTAL_ELEVATIONS/>">"
<"<"TRANSMITTER>">"
<"<"EQP_EQUIP_NAME>">"kCstring (128)<"<"/EQP_EQUIP_NAME/>">"
<"<"EQP_EQUIP_TYPE>">"kCstring (16)<"<"/EQP_EQUIP_TYPE/>">"
<"<"FREQUENCY>">"
<"<"EFL_FREQ>">"kCdouble<"<"/EFL_FREQ/>">"
<"<"COORDINATED_FREQUENCY>">"
<"<"COF_DAT>">"kWrDate<"<"/COF_DAT/>">"
<"<"/COORDINATED_FREQUENCY/>">"
<"<"/FREQUENCY/>">"
<"<"/TRANSMITTER/>">"
<"<"/STATION/>">"
<"<"/APPLICATION/>">"
<"<"/SPECTRAEXCHANGE/>">" 

First I created the table SPECTRAEXCHANGE and than I want to use the following commands:

INSERT INTO TABLENAME(SV_SV_ID,
SS_SS_ID,
AP_NAME,
AP_PRJ_IDENT )
WITH t AS (SELECT xmltype(bfilename('TEST_DIR','yourXMLFileName.xml'), nls_charset_id('WE8ISO8859P1')) xmlcol FROM dual)
SELECT
extractValue(value(x),'/APPLICATION/SV_SV_ID') SV_SV_ID /* value will be kClong */
,extractValue(value(x),'/APPLICATION/SS_SS_ID') SS_SS_ID /* value will be kClong*/
,extractValue(value(x),'APPLICATION/AP_NAME') AP_NAME /* value will be kCstring (64)*/
,extractValue(value(x),'APPLICATION/AP_PRJ_IDENT') AP_PRJ_IDENT
FROM t,TABLE(XMLSequence(extract(t.xmlcol,'/SPECTRAEXCHANGE/APPLICATION'))) x;


UPDATE SPECTRAEXCHANGE SET TCS_NAME = extractValue(value(x),'/APPLICATION/STATION/TCS_NAME'),
TCS_CALL = extractValue(value(x),'/APPLICATION/STATION/TCS_CALL')
WITH t AS (SELECT xmltype(bfilename('TEST_DIR','yourXMLFileName.xml'), nls_charset_id('WE8ISO8859P1')) xmlcol FROM dual)
FROM t,TABLE(XMLSequence(extract(t.xmlcol,'/SPECTRAEXCHANGE/APPLICATION/STATION'))) x;

etc..

And in UPDATE session I got error message: 00933. 00000 - "SQL command not properly ended"

And I tried this for UPDATE session:

UPDATE SPECTRAEXCHANGE SET
TCS_NAME = x.TCS_NAME,
TCS_CALL = x.TCS_CALL
WITH t AS (SELECT xmltype(bfilename('TEST_DIR','yourXMLFileName.xml'), nls_charset_id('WE8ISO8859P1')) xmlcol FROM dual)
SELECT
extractValue(value(x),'APPLICATION/STATION/TCS_NAME') TCS_NAME
,extractValue(value(x),'APPLICATION/STATION/TCS_CALL') TCS_CALL
FROM t,TABLE(XMLSequence(extract(t.xmlcol,'/SPECTRAEXCHANGE/APPLICATION/STATION'))) x; 

but unfortunatly it doesn't work... so can you help me with update part? or give me other tutorial to import xml with more than one node. thanks. Milan

2
  • 2
    Does that XML validate in any way or form? Does not look like any XML I've seen before. Commented May 3, 2013 at 7:08
  • the starting and ending tags aren't the 'normal' Commented May 3, 2013 at 8:51

1 Answer 1

1

You're trying to update two columns from a subquery, but your syntax is wrong; it should be more like:

update tablename set (col1 = val1, col2 = val2)
select (val1, val 2 from ...)

In your case something like this, assuming you're inserting and updating the same table, and passing the (modified) raw XML as an SQL*Plus var for my testing:

create table spectraexchange(sv_sv_id varchar2(15), ss_ss_id varchar2(15),
    ap_name varchar2(15), ap_prj_ident varchar2(15),
    tcs_name varchar2(15), tcs_call varchar2(15));

Table created.

insert into spectraexchange(sv_sv_id, ss_ss_id, ap_name, ap_prj_ident)
select extractvalue(value(x), 'APPLICATION/SV_SV_ID') sv_sv_id,
    extractvalue(value(x), 'APPLICATION/SS_SS_ID') ss_ss_id,
    extractvalue(value(x), 'APPLICATION/AP_NAME') ap_name,
    extractvalue(value(x), 'APPLICATION/AP_PRJ_IDENT') ap_prj_ident
from (
    select xmltype(:raw_xml) xmlcol from dual
) t
cross join table(XMLSequence(extract(t.xmlcol,
    '/SPECTRAEXCHANGE/APPLICATION'))) x;

1 row created.

select * from spectraexchange;

SV_SV_ID        SS_SS_ID        AP_NAME         AP_PRJ_IDENT    TCS_NAME        TCS_CALL
--------------- --------------- --------------- --------------- --------------- ---------------
kClong          kClong          kCstring (64)   kCstring (32)

Then the update could be:

update spectraexchange
set (tcs_name, tcs_call) = (
    select extractvalue(value(x), 'STATION/TCS_NAME'),
        extractvalue(value(x), 'STATION/TCS_CALL')
    from (
        select xmltype(:raw_xml) xmlcol from dual
    ) t
    cross join table(XMLSequence(extract(t.xmlcol,
        '/SPECTRAEXCHANGE/APPLICATION/STATION'))) x
);

1 row updated.

select * from spectraexchange;

SV_SV_ID        SS_SS_ID        AP_NAME         AP_PRJ_IDENT    TCS_NAME        TCS_CALL
--------------- --------------- --------------- --------------- --------------- ---------------
kClong          kClong          kCstring (64)   kCstring (32)   kCstring (64)   kCstring (256)

If course this also assumes one station per application, otherwise you'll need multiple joined tables to hold the relationships I guess; and only one application or your update would need to be correlated somehow. But then the update seems pointless, you could do it all on insert:

insert into spectraexchange(sv_sv_id, ss_ss_id, ap_name, ap_prj_ident,
    tcs_name, tcs_call)
select extractvalue(value(x), 'APPLICATION/SV_SV_ID') sv_sv_id,
    extractvalue(value(x), 'APPLICATION/SS_SS_ID') ss_ss_id,
    extractvalue(value(x), 'APPLICATION/AP_NAME') ap_name,
    extractvalue(value(x), 'APPLICATION/AP_PRJ_IDENT') ap_prj_ident,
    extractvalue(value(x), 'APPLICATION/STATION/TCS_NAME') tcs_name,
    extractvalue(value(x), 'APPLICATION/STATION/TCS_CALL') tcs_call
from (
    select xmltype(:raw_xml) xmlcol from dual
) t
cross join table(XMLSequence(extract(t.xmlcol,
    '/SPECTRAEXCHANGE/APPLICATION'))) x;

... (which only works with one-to-one relationships) so clearly I'm missing something from the picture.


Based on your comments that you have one-to-many relationships and you're inserting everything into one table (!?), you can do this instead:

insert into spectra exchange ( ... columns ... )
select a.sv_sv_id, a.ss_ss_id, a.ap_name, a.ap_prj_ident,
    s.tcs_name, s.tcs_call,
    t.eqp_equip_name, t.eqp_equip_type
from (select xmltype(:raw_xml) xmlcol from dual) r
cross join xmltable('/SPECTRAEXCHANGE/APPLICATION' passing r.xmlcol
        columns sv_sv_id varchar2(15) path 'SV_SV_ID',
            ss_ss_id varchar2(15) path 'SS_SS_ID',
            ap_name varchar2(15) path 'AP_NAME',
            ap_prj_ident varchar2(15) path 'AP_PRJ_IDENT',
            stations xmltype path 'STATION'
    ) (+) a
cross join xmltable('/STATION' passing a.stations
        columns tcs_name varchar2(15) path 'TCS_NAME',
            tcs_call varchar2(15) path 'TCS_CALL',
            transmitter xmltype path 'TRANSMITTER'
    ) (+) s
cross join xmltable('/TRANSMITTER' passing s.transmitter
        columns eqp_equip_name varchar2(15) path 'EQP_EQUIP_NAME',
            eqp_equip_type varchar2(15) path 'EQP_EQUIP_TYPE',
            frequency xmltype path 'FREQUENCY'
    ) (+) t
/

I've gone down an extra level to transmitter, and you can just repeat the pattern to add more, passing the relevant node down each time. The outer joins (+) will allow for some things not existing, e.g. if you have a transmitter that hasn't been given a frequency yet, or whatever - you'll get a null in the relevant columns.

Sign up to request clarification or add additional context in comments.

13 Comments

Thanks, but I got error message: 01427. 00000 - "single-row subquery returns more than one row"
@user2342549 - with the data you showed, or a larger sample that has multiple applications and/or stations? I think you need to be clearer what you're trying to achieve and how the data will be arranged in tables; adding the table schema(s) to the question would probably help.
i would like to import more rows in update part, and the insert into part contain more rows.
you are right, I have multiple applications and station and etc.
@user2342549 - ok, then you're probably not storing everything in one table, you'll have an applications table and a stations table with a one-to-many relationship? Please add that info to the question, including table definitions and relationships.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.