Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Verwendung einer Variablen zum Definieren des Pfads in XMLTable in Oracle

Ich laufe zu demselben Problem (beide in 11.2.0.3.0 und 12.1.0.2.0). Anscheinend können Sie anstelle von XQuery_string keine PL/SQL-Variable verwenden unter xmltable wenn die Abfragezeichenfolge auf einen Namespace verweist. Beachten Sie, dass Sie eine PL/SQL-Variable verwenden können, wenn Sie keinen Namespace referenzieren (siehe Beispiel Nr. 3 unten).

Die ausgelöste Ausnahme Beschreibung :

Wenn die Tatsache, dass eine Variable anstelle eines Zeichenfolgenliterals verwendet wird, von Oracle veraltet zu sein scheint. Oracle Support-Dokument Doc ID 1490150.1 (nur für zahlende Kunden verfügbar) schlägt vor, dass es einen Patch gibt (der Fall ist nicht genau derselbe wie unser Fall, aber sehr ähnlich), aber das Dokument besagt auch Folgendes:

  • Die Verwendung einer Variablen anstelle eines String-Literals ist kein SQL/XML-Standardverhalten
  • Das Erstellen von XPath/XQuery während der Laufzeit hat eine schwerwiegende Leistungseinbuße

Daher empfiehlt Oracle, nur Zeichenfolgenliterale zu verwenden.

Meine anfängliche Verwirrung wurde durch den folgenden Konflikt in Oracles eigener Dokumentation (11.2) verursacht:

XMLTABLE SQL/XML-Funktion in Oracle XML DB im XML-DB-Entwicklerhandbuch :

XMLTABLE in Datenbank-SQL-Sprachreferenz :

Beachten Sie das fehlende "as a string literal" aus dem zweiten Zitat. Und natürlich habe ich zuerst nur Database SQL Language Reference gelesen ...

Die XMLTABLE-Dokumentation wurde in Version 12.1 korrigiert :

Die Antwort lautet also, dass Sie keine Variable als XQuery_string verwenden es lässt sich sogar kompilieren und scheint in manchen Fällen zu funktionieren.

Unten finden Sie minimale Beispiele, um das Problem zu reproduzieren:

Beispiel 1

Das funktioniert und druckt 'This is A.' wie erwartet.

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

Beispiel 2

Dies schlägt fehl mit:

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

Beispiel #3

Das funktioniert und druckt 'This is A.' wie erwartet.

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