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