Zdá se, že jde o velmi zvláštní požadavek, který bude obtížné vyřešit robustním způsobem. STMT_OR_VALUE je ztělesněním anti-vzoru One Column Two Usages. Rozložení STMT_OR_VALUE navíc vyžaduje logiku řízení toku a použití dynamického SQL. V důsledku toho to nemůže být čisté řešení SQL:k sestavení a provedení dynamického dotazu musíte použít PL/SQL.
Zde je důkaz koncepce řešení. Rozhodl jsem se pro funkci, kterou můžete volat z SQL. Závisí to na jednom předpokladu:každý řetězec dotazu, který vložíte do TEST1.STMT_OR_VALUE, má projekci jednoho číselného sloupce a každý řetězec hodnot je pouze CSV s číselnými údaji . S touto výhradou je snadné vytvořit funkci, která buď provede dynamický dotaz, nebo tokenizuje řetězec na řadu čísel; oba jsou hromadně shromážděny do vnořené tabulky:
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;
/
Všimněte si, že existuje více než jeden způsob provádění dynamického příkazu SQL a mnoho způsobů, jak tokenizovat CSV na řadu čísel. Moje rozhodnutí jsou svévolná:zde můžete nahradit své preferované metody.
Tuto funkci lze vyvolat pomocí table()
zavolejte:
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
/
Velkou výhodou tohoto přístupu je, že zapouzdřuje logiku kolem vyhodnocení STMT_OR_VALUE a skrývá použití dynamického SQL. V důsledku toho je snadné jej použít v jakémkoli SQL příkazu při zachování čitelnosti nebo přidat další mechanismy pro generování sady ID.
Toto řešení je však křehké. Bude fungovat pouze v případě, že hodnoty v test1
stůl dodržovat pravidla. To znamená, že musí být nejen konvertibilní na proud jednotlivých čísel, ale příkazy SQL musí být platné a spustitelné příkazem EXECUTE IMMEDIATE. Například koncový středník ve vzorových datech otázky je neplatný a způsobil by vrhnutí EXECUTE IMMEDIATE. Dynamické SQL je obtížné v neposlední řadě proto, že převádí chyby kompilace na chyby za běhu.