私はこれとまったく同じ問題に遭遇します(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開発者ガイド :
欠落している「文字列リテラルとして」に注意してください 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;
/