Разбор большого XML (> 4k) в PL / SQL - PullRequest
2 голосов
/ 08 ноября 2011

Я получаю XML длиной около 30 КБ.Я должен извлечь пары ключ-значение из этого XML и вставить в таблицу.Также следует избегать дублирования строк в таблице.Вот запрос, который я получил:

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;

Этот запрос работает нормально и, наконец, будет частью sproc.

Здесь у меня есть два вопроса:

1- Это правильный способ обработки большого xml максимального размера 32k.

2- Будет ли это достаточно эффективно для обработки 700звонки в секунду?

Спасибо, Attiq

1 Ответ

1 голос
/ 30 мая 2012

Я думаю, что вы определенно хотите собрать вкладки, по крайней мере.Я не знаю, насколько велика NODELENGTH, но вы можете использовать что-то похожее на:

В вашей объявленной части:

TYPE T_STRING IS TABLE OF VARCHAR2(1024); -- adjust size
arr T_STRING    := T_STRING();

в теле тела:

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);

Я также не знаю, какова цель несуществующей части, вы уверены, что это необходимо?

...