sql >> Databáze >  >> RDS >> Oracle

Použití proměnné k definování cesty v XMLTable v Oracle

Narazil jsem na stejný problém (v 11.2.0.3.0 a 12.1.0.2.0). Vypadá to, že místo XQuery_string nemůžete použít proměnnou PL/SQL na xmltable když řetězec dotazu odkazuje na jmenný prostor. Všimněte si, že můžete použít proměnnou PL/SQL, pokud neodkazujete na jmenný prostor (viz příklad č. 3 níže).

Vyvolaná výjimka popis :

Pokud se zdá, že použití proměnné místo řetězcového literálu je společností Oracle zastaralé. Dokument podpory Oracle Doc ID 1490150.1 (dostupný pouze pro platící zákazníky) naznačuje, že existuje oprava (případ není úplně stejný jako náš případ, ale velmi podobný), ale dokument také uvádí, že:

  • Použití proměnné místo řetězcového literálu není standardní chování SQL/XML
  • konstruování XPath/XQuery za běhu má vážné omezení výkonu

A proto Oracle doporučuje používat pouze řetězcové literály.

Můj počáteční zmatek byl způsoben následujícím konfliktem ve vlastní dokumentaci Oracle (11.2):

Funkce XMLTABLE SQL/XML v Oracle XML DB v Příručce pro vývojáře XML DB :

XMLTABLE v Reference jazyka SQL databáze :

Všimněte si chybějícího "jako řetězcový literál" z druhého citátu. A samozřejmě jsem nejprve četl pouze Odkaz na jazyk SQL databáze ...

Dokumentace XMLTABLE byla opravena ve verzi 12.1 :

Takže odpověď je, že nepoužívejte proměnnou jako XQuery_string dokonce se zkompiluje a v některých případech se zdá, že funguje.

Níže naleznete minimální příklady pro reprodukci problému:

Příklad č. 1

Toto funguje a vytiskne 'Toto je A.' podle očekávání.

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

Příklad č. 2

Toto selže s:

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

Příklad č. 3

Toto funguje a vytiskne 'Toto je A.' podle očekávání.

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. Proč při vytváření tohoto jednoduchého příkladu materializovaného pohledu dochází k chybě ORA-12054?

  2. Jak by se dal tento dotaz vylepšit?

  3. SQLException:Nelze načíst stavový server transakce pouze pro čtení

  4. Databázové tipy pro začátečníky