2011-11-08 10 views
2

長さ約30kのxmlを取得しています。私は、このXMLからキーと値のペアを抽出し、テーブルに挿入する必要があります。また、テーブルの重複した行を避ける必要があります。ここに私が思い付いたクエリは次のとおりです。PL/SQLで大きなXML(> 4k)を解析する

DECLARE 
    PARSER XMLPARSER.PARSER; 
    XMLDOC XMLDOM.DOMDOCUMENT; 
    NODELIST XMLDOM.DOMNODELIST; 
    REFDATA VARCHAR2(32767); 
    REFDATAPART VARCHAR2(32767); 
    NODELENGTH NUMBER; 

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をBEGIN;

このクエリは正常に動作し、最後にsprocの一部になります。

1-これは最大サイズの32Kの大規模なXMLを処理するための正しい方法です:

は、ここで私は2つの質問があります。

2- 1秒間に700回のコールを処理するのに十分効率的ですか?

おかげで、 Attiq

+0

"これは、1秒間に700回のコールを処理するのに十分効率的ですか? - これは何のハードウェアが走っているのか、これを走らせるものなのですか?これはあなたが答えることができる質問です。個人的には、データベースでこの種の処理を行うのではなく、むしろアプリケーションサーバーで行うことになります。 –

+0

XMLTYPEを見ることもできます。私の考えでは、XMLPARSERよりも扱いが簡単です。それが良いかどうかは分かりません。 32Kは問題を引き起こすべきではありませんが、サイズのMBのXMLを使用してXMLTYPEでパフォーマンスの問題が発生しています。 700 tpsについては、重いXMLの持ち上げを行い、両方のアプローチのパフォーマンスを比較するために、中間層のアプリケーションサーバーを使用します。 –

答えて

1

私は、あなたは間違いなく、少なくとも挿入を収集したいと思います。私はNODELENGTHがいかに大きいかわからないが、あなたは次のように何かを使用することができます:私もない

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

:PL本体内

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

:あなたの宣言部分で

を存在しない部分の目的が何であるか知っています、これは必要であると確信していますか?

関連する問題