sql >> データベース >  >> RDS >> Oracle

OracleのXMLTableでパスを定義するための変数の使用

    私はこれとまったく同じ問題に遭遇します(11.2.0.3.0と12.1.0.2.0の両方)。 XQuery_stringの代わりにPL/SQL変数を使用できないようです。 xmltable で クエリ文字列が名前空間を参照する場合。名前空間を参照しない場合は、PL / SQL変数を使用できることに注意してください(以下の例3を参照)。

    発生した例外説明 :

    文字列リテラルの代わりに変数を使用するという事実がOracleによって非推奨になっているように思われる場合。 OracleサポートドキュメントのドキュメントID1490150.1(有料のお客様のみが利用可能)は、パッチがあることを示唆しています(ケースは私たちのケースとまったく同じではありませんが、非常に似ています)が、ドキュメントには次のようにも記載されています。

    • 文字列リテラルの代わりに変数を使用することは、SQL/XMLの標準的な動作ではありません
    • 実行時にXPath/XQueryを構築すると、パフォーマンスが大幅に低下します

    したがって、文字列リテラルのみを使用することをお勧めします。

    私の最初の混乱は、Oracle自身のドキュメント(11.2)の次の競合が原因でした。

    OracleXMLDBのXMLTABLESQL/XML関数 XMLDB開発者ガイド

    XMLTABLE データベースSQL言語リファレンス

    欠落している「文字列リテラルとして」に注意してください 2番目の引用から。そしてもちろん、私は最初にデータベースSQL言語参照のみを読み取りました。 ...

    XMLTABLEのドキュメントは、12.1バージョン で修正されました。 :

    したがって、答えは、変数を XQuery_stringとして使用しないことです。 コンパイルしても、場合によっては機能するようです。

    以下に、問題を再現するための最小限の例を示します。

    例1

    これは動作し、「これはAです」と出力します。予想通り。

    declare
      v_xml constant xmltype := xmltype('
    <ns:a
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:ns="http://stackoverflow.com/users/272735/a">
      <foo><bar>This is A.</bar></foo>
    </ns:a>
    ');
      v_content varchar2(100);
    begin
      select bar into v_content
      from xmltable(
        xmlnamespaces('http://stackoverflow.com/users/272735/a' as "ns")
        ,'/ns:a/foo' passing v_xml
        columns
        bar varchar2(4000) path 'bar'
      );
    
      dbms_output.put_line(v_content);
    end;
    /
    

    例2

    これは次の場合に失敗します:

    ORA-19112: error raised during evaluation:
    XVM-01081: [XPST0081] Invalid prefix
    1   /ns:a/foo
    -   ^
    

    declare
      v_xml constant xmltype := xmltype('
    <ns:a
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:ns="http://stackoverflow.com/users/272735/a">
      <foo><bar>This is A.</bar></foo>
    </ns:a>
    ');
      v_xquery_string constant varchar2(100) := '/ns:a/foo';
      v_content varchar2(100);
    begin
      select bar into v_content
      from xmltable(
        xmlnamespaces('http://stackoverflow.com/users/272735/a' as "ns")
        ,v_xquery_string passing v_xml
        columns
        bar varchar2(4000) path 'bar'
      );
    
      dbms_output.put_line(v_content);
    end;
    /
    

    例3

    これは動作し、「これはAです」と出力します。予想通り。

    declare
      v_xml constant xmltype := xmltype('<a><foo><bar>This is A.</bar></foo></a>');
      v_xquery_string constant varchar2(100) := '/a/foo';
      v_content varchar2(100);
    begin
      select bar into v_content
      from xmltable(
        v_xquery_string passing v_xml
        columns
        bar varchar2(4000) path 'bar'
      );
    
      dbms_output.put_line(v_content);
    end;
    /
    


    1. 実績/バッジシステム

    2. ゼロデータロスリカバリアプライアンス

    3. パラメータが入力されていない場合、where句の日付範囲パラメータを無視します

    4. Oracleで全表スキャンを検索するためのクエリ