Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Użycie zmiennej do zdefiniowania ścieżki w XMLTable w Oracle

Docieram do tego samego problemu (zarówno w wersji 11.2.0.3.0, jak i 12.1.0.2.0). Wygląda na to, że nie możesz użyć zmiennej PL/SQL zamiast XQuery_string w xmltable gdy ciąg zapytania odwołuje się do przestrzeni nazw. Zauważ, że możesz użyć zmiennej PL/SQL, jeśli nie odwołujesz się do przestrzeni nazw (patrz przykład #3 poniżej).

Zgłoszony wyjątek opis :

Jeśli fakt używania zmiennej zamiast literału znakowego wydaje się być przestarzały przez Oracle. Dokument pomocy technicznej Oracle Doc ID 1490150.1 (dostępny tylko dla klientów płacących) sugeruje, że istnieje poprawka (przypadek nie jest dokładnie taki sam jak w naszym przypadku, ale bardzo podobny), ale dokument stwierdza również, że:

  • używanie zmiennej zamiast literału ciągu nie jest standardowym zachowaniem SQL/XML
  • konstruowanie XPath/XQuery w czasie wykonywania ma poważny spadek wydajności

Dlatego Oracle zaleca używanie tylko literałów łańcuchowych.

Moje początkowe zamieszanie było spowodowane następującym konfliktem we własnej dokumentacji Oracle (11.2):

Funkcja XMLTABLE SQL/XML w bazie danych Oracle XML w Podręczniku programisty XML DB :

XMLTABLE w Informacje o języku bazy danych SQL :

Zwróć uwagę na brak „jako literał ciągu” z drugiego cytatu. I oczywiście najpierw przeczytałem tylko Informacje o języku SQL w bazie danych ...

Dokumentacja XMLTABLE została poprawiona w wersja 12.1 :

Odpowiedź brzmi:nie używaj zmiennej jako XQuery_string nawet się kompiluje i w niektórych przypadkach wydaje się działać.

Poniżej znajdziesz minimalne przykłady odtworzenia problemu:

Przykład #1

To działa i drukuje „To jest A”. zgodnie z oczekiwaniami.

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

Przykład #2

To się nie udaje z:

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

Przykład #3

To działa i drukuje „To jest A”. zgodnie z oczekiwaniami.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak radzić sobie z oszczędzaniem światła dziennego w bazie danych Oracle

  2. Dołącz do forum pytań i odpowiedzi dla programistów

  3. Usuń nagłówek kolumny do wyjściowego pliku tekstowego

  4. Oracle — jak utworzyć użytkownika tylko do odczytu

  5. Jak obsłużyć wyjątki to_date w instrukcji SELECT, aby zignorować te wiersze?