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.