sql >> Base de Datos >  >> RDS >> Oracle

Uso de variable para definir la ruta en XMLTable en Oracle

Me encuentro con este mismo problema (tanto en 11.2.0.3.0 como en 12.1.0.2.0). Parece que no puede usar una variable PL/SQL en lugar de XQuery_string en xmltable cuando la cadena de consulta hace referencia a un espacio de nombres. Tenga en cuenta que puede usar una variable PL/SQL si no hace referencia a un espacio de nombres (consulte el ejemplo n.° 3 a continuación).

La excepción planteada descripción :

Si el hecho de usar una variable en lugar de un literal de cadena parece estar obsoleto por Oracle. El documento de soporte de Oracle Doc ID 1490150.1 (solo disponible para clientes que pagan) sugiere que hay un parche (el caso no es exactamente el mismo que nuestro caso pero es muy similar) pero el documento también establece que:

  • usar una variable en lugar de un literal de cadena no es un comportamiento estándar de SQL/XML
  • construir XPath/XQuery durante el tiempo de ejecución tiene una grave penalización de rendimiento

Y, por lo tanto, Oracle recomienda usar solo literales de cadena.

Mi confusión inicial fue causada por el siguiente conflicto en la propia documentación de Oracle (11.2):

Función XMLTABLE SQL/XML en Oracle XML DB en Guía del desarrollador de base de datos XML :

XMLTABLE en Referencia del lenguaje SQL de la base de datos :

Tenga en cuenta que falta "como un literal de cadena" de la segunda cita. Y, por supuesto, primero leí solo Referencia del lenguaje SQL de la base de datos ...

La documentación de XMLTABLE se ha corregido en la versión 12.1 :

Entonces la respuesta es que no use una variable como XQuery_string incluso compila y en algunos casos parece funcionar.

A continuación, encontrará ejemplos mínimos para reproducir el problema:

Ejemplo #1

Esto funciona e imprime 'Esto es A.' como se esperaba.

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

Ejemplo #2

Esto falla con:

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

Ejemplo #3

Esto funciona e imprime 'Esto es A.' como se esperaba.

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