I am getting an xml of length around 30k. I have to extract key and value pairs from this xml and insert into a table. Also have to avoid from duplicated rows in table. Here is the query I came up with:
DECLARE
PARSER XMLPARSER.PARSER;
XMLDOC XMLDOM.DOMDOCUMENT;
NODELIST XMLDOM.DOMNODELIST;
REFDATA VARCHAR2(32767);
REFDATAPART VARCHAR2(32767);
NODELENGTH NUMBER;
BEGIN
REFDATA := '<ReferenceFields><ReferenceField><FieldKey>Name1</FieldKey> <FieldValue>ABCD</FieldValue></ReferenceField><ReferenceField><FieldKey>Name1</FieldKey><FieldValue>ABCD</FieldValue></ReferenceField></ReferenceFields>';
PARSER := XMLPARSER.NEWPARSER;
XMLPARSER.PARSEBUFFER(PARSER,REFDATA);
XMLDOC := XMLPARSER.GETDOCUMENT(PARSER);
NODELIST := XMLDOM.GETELEMENTSBYTAGNAME(XMLDOC, 'ReferenceField');
NODELENGTH := XMLDOM.GETLENGTH(NODELIST);
FOR i IN 0..NODELENGTH-1 LOOP
XMLDOM.WRITETOBUFFER(XMLDOM.ITEM(NODELIST, i),REFDATAPART);
INSERT INTO
HTS_TRANSACTION_XREF(TRANS_ID,XREF_FIELD, XREF_VALUE)
SELECT
'1',
EXTRACTVALUE(COLUMN_VALUE, '/ReferenceField/FieldKey') "FIELDKEY",
EXTRACTVALUE(COLUMN_VALUE, '/ReferenceField/FieldValue') "FIELDVALUE"
FROM
TABLE(XMLSequence(XMLTYPE(REFDATAPART))) REFDATA
WHERE
NOT EXISTS (SELECT 1 from TRANSACTION_CROSSREFERENCE WHERE TRANS_ID='1' AND XREF_FIELD=EXTRACTVALUE(column_value, '/ReferenceField/FieldKey') AND XREF_VALUE=EXTRACTVALUE(column_value, '/ReferenceField/FieldValue'));
END LOOP;
XMLPARSER.FREEPARSER(PARSER);
END;
This query works fine and finally would be part of sproc.
Here I have two questions:
1- Is this the right way to process large xml of maximum size 32k.
2- Will this be efficient enough to handle 700 calls in a second?
Thanks, Attiq
I think that you definitely want to gather the inserts at least. I don't know how big is NODELENGTH but you may use something similar to:
In your declare part:
TYPE T_STRING IS TABLE OF VARCHAR2(1024); -- adjust size
arr T_STRING := T_STRING();
in the pl body:
REFDATA := '<ReferenceFields><ReferenceField><FieldKey>Name1</FieldKey> <FieldValue>ABCD</FieldValue></ReferenceField><ReferenceField><FieldKey>Name1</FieldKey><FieldValue>ABCD</FieldValue></ReferenceField></ReferenceFields>';
PARSER := XMLPARSER.NEWPARSER;
XMLPARSER.PARSEBUFFER(PARSER,REFDATA);
XMLDOC := XMLPARSER.GETDOCUMENT(PARSER);
NODELIST := XMLDOM.GETELEMENTSBYTAGNAME(XMLDOC, 'ReferenceField');
NODELENGTH := XMLDOM.GETLENGTH(NODELIST);
FOR i IN 0..NODELENGTH-1 LOOP
XMLDOM.WRITETOBUFFER(XMLDOM.ITEM(NODELIST, i), REFDATAPART);
arr.EXTEND();
arr(arr.COUNT) := XMLSequence(XMLTYPE(REFDATAPART));
END LOOP;
FORALL i IN arr.FIRST..arr.LAST
INSERT INTO HTS_TRANSACTION_XREF(TRANS_ID,XREF_FIELD, XREF_VALUE)
SELECT
'1',
EXTRACTVALUE(arr(i), '/ReferenceField/FieldKey') "FIELDKEY",
EXTRACTVALUE(arr(i), '/ReferenceField/FieldValue') "FIELDVALUE"
FROM
dual
WHERE
NOT EXISTS (
SELECT 1 FROM TRANSACTION_CROSSREFERENCE
WHERE
TRANS_ID = '1'
AND XREF_FIELD = EXTRACTVALUE(arr(i), '/ReferenceField/FieldKey')
AND XREF_VALUE = EXTRACTVALUE(arr(i), '/ReferenceField/FieldValue')
);
XMLPARSER.FREEPARSER(PARSER);
I also don't know what is the purpose of the not exists part, are you sure this is necessary?