Oracle
 sql >> Database >  >> RDS >> Oracle

Utilizzo della variabile per definire il percorso in XMLTable in Oracle

Corro a questo stesso problema (sia in 11.2.0.3.0 che 12.1.0.2.0). Sembra che tu non possa usare una variabile PL/SQL al posto di XQuery_string su xmltable quando la stringa di query fa riferimento a uno spazio dei nomi. Nota che puoi utilizzare una variabile PL/SQL se non fai riferimento a uno spazio dei nomi (vedi esempio n. 3 di seguito).

L'eccezione sollevata descrizione :

Se il fatto che utilizza una variabile invece di una stringa letterale sembra essere deprecato da Oracle. Il documento di supporto Oracle Doc ID 1490150.1 (disponibile solo per i clienti paganti) suggerisce che esiste una patch (il caso non è esattamente lo stesso del nostro caso ma è molto simile) ma il documento afferma anche che:

  • l'uso di una variabile invece di una stringa letterale non è un comportamento standard SQL/XML
  • La costruzione di XPath/XQuery durante il runtime comporta una grave penalizzazione delle prestazioni

E quindi Oracle consiglia di utilizzare solo stringhe letterali.

La mia confusione iniziale è stata causata dal seguente conflitto nella documentazione di Oracle (11.2):

Funzione XMLTABLE SQL/XML nel DB Oracle XML in Guida per sviluppatori XML DB :

XMLTABLE in Riferimento al linguaggio SQL del database :

Nota il "come stringa letterale" mancante dalla seconda citazione. E ovviamente prima leggo solo Database SQL Language Reference ...

La documentazione XMLTABLE è stata corretta in versione 12.1 :

Quindi la risposta è che non usa una variabile come XQuery_string anche si compila e in alcuni casi sembra funzionare.

Di seguito troverai esempi minimi per riprodurre il problema:

Esempio n. 1

Funziona e stampa 'This is A.' come previsto.

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

Esempio n. 2

Questo non riesce 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;
/

Esempio n. 3

Funziona e stampa 'This is A.' come previsto.

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