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

wykonać zapytanie SQL zapisane w tabeli

Wydaje się to bardzo osobliwym wymogiem, który będzie trudny do rozwiązania w solidny sposób. STMT_OR_VALUE jest ucieleśnieniem antywzorca One Column Two Usages. Ponadto rozwiązanie STMT_OR_VALUE wymaga logiki sterowania przepływem i użycia dynamicznego SQL. W związku z tym nie może to być rozwiązanie oparte na czystym SQL:musisz użyć PL/SQL do asemblacji i wykonania dynamicznego zapytania.

Oto dowód koncepcji rozwiązania. Wybrałem funkcję, którą można wywołać z SQL. Zależy to od jednego założenia:każdy ciąg zapytania, który wstawisz do TEST1.STMT_OR_VALUE ma odwzorowanie pojedynczej kolumny liczbowej a każdy ciąg wartości to plik CSV zawierający tylko dane liczbowe . Z tym zastrzeżeniem można łatwo skonstruować funkcję, która albo wykonuje dynamiczne zapytanie, albo tokenizuje ciąg w serię liczb; oba są zbierane zbiorczo w zagnieżdżonej tabeli:

create or replace function get_ids (p_name in test1.name%type) 
  return sys.odcinumberlist
is
  l_rec test1%rowtype;
  return_value sys.odcinumberlist;
begin

  select * into l_rec
  from test1
  where name = p_name;

  if l_rec.type = 'SQL_QUERY' then 
    -- execute a query
    execute immediate l_rec.stmt_or_value
      bulk collect into return_value;
  else
    -- tokenize a string
    select xmltab.tkn
    bulk collect into return_value
    from ( select l_rec.stmt_or_value from dual) t
        , xmltable(  'for $text in ora:tokenize($in, ",") return $text'
                      passing stmt_or_value as "in"
                      columns tkn number path '.'
                   ) xmltab;
  end if;
  return return_value;
end;
/

Zauważ, że istnieje więcej niż jeden sposób wykonania dynamicznej instrukcji SQL i wiele sposobów na tokenizację pliku CSV w serię liczb. Moje decyzje są arbitralne:możesz tutaj zastąpić preferowane metody.

Ta funkcja może być wywołana za pomocą table() zadzwoń:

select * 
from data
where id in ( select * from table(get_ids('first'))) -- execute query
or    id in ( select * from table(get_ids('second'))) -- get string of values
/

Dużą zaletą tego podejścia jest hermetyzacja logiki wokół oceny STMT_OR_VALUE i ukrywanie użycia dynamicznego SQL. W związku z tym łatwo jest zastosować go w dowolnej instrukcji SQL, zachowując czytelność, lub dodać kolejne mechanizmy generowania zestawu identyfikatorów.

Jednak to rozwiązanie jest kruche. Będzie działać tylko wtedy, gdy wartości w test1 stół przestrzegać zasad. Oznacza to, że nie tylko muszą być konwertowalne na strumień pojedynczych liczb, ale instrukcje SQL muszą być poprawne i możliwe do wykonania przez EXECUTE IMMEDIATE. Na przykład końcowy średnik w przykładowych danych pytania jest nieprawidłowy i spowodowałby uruchomienie polecenia EXECUTE IMMEDIATE. Dynamiczny SQL jest trudny nie tylko dlatego, że konwertuje błędy kompilacji na błędy wykonawcze.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. przekonwertuj na PROCEDURA pl/sql

  2. Łączenie tabel w Oracle SQL Developer

  3. nhibernate, wywołaj funkcję w Oracle, która zwraca refcursor sys

  4. ORA-01036:nieprawidłowa nazwa/numer zmiennej podczas wywoływania zapisanej funkcji

  5. Łączenie się z bazą danych Oracle za pomocą Swift po stronie serwera