Cela semble une exigence très particulière, et qui sera difficile à résoudre de manière robuste. STMT_OR_VALUE est l'incarnation de l'anti-pattern One Column Two Usages. De plus, la résolution de STMT_OR_VALUE nécessite une logique de contrôle de flux et l'utilisation de SQL dynamique. Par conséquent, il ne peut pas s'agir d'une solution purement SQL :vous devez utiliser PL/SQL pour assembler et exécuter la requête dynamique.
Voici une preuve de concept pour une solution. J'ai opté pour une fonction que vous pouvez appeler depuis SQL. Cela dépend d'une hypothèse :chaque chaîne de requête que vous insérez dans TEST1.STMT_OR_VALUE a une projection d'une seule colonne numérique et chaque chaîne de valeur est un CSV de données numériques uniquement . Avec cette condition, il est simple de construire une fonction qui exécute une requête dynamique ou segmente la chaîne en une série de nombres ; qui sont tous deux collectés en masse dans une table imbriquée :
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;
/
Notez qu'il existe plusieurs façons d'exécuter une instruction SQL dynamique et une multiplicité de façons de segmenter un CSV en une série de nombres. Mes décisions sont arbitraires :n'hésitez pas à substituer vos méthodes préférées ici.
Cette fonction peut être invoquée avec un table()
appeler :
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
/
Le grand avantage de cette approche est qu'elle encapsule la logique autour de l'évaluation de STMT_OR_VALUE et masque l'utilisation de Dynamic SQL. Par conséquent, il est facile de l'utiliser dans n'importe quelle instruction SQL tout en conservant la lisibilité, ou d'ajouter d'autres mécanismes pour générer un ensemble d'ID.
Cependant, cette solution est fragile. Cela ne fonctionnera que si les valeurs dans le test1
table obéir aux règles. Autrement dit, non seulement ils doivent être convertibles en un flux de nombres uniques, mais les instructions SQL doivent être valides et exécutables par EXECUTE IMMEDIATE. Par exemple, le point-virgule final dans les exemples de données de la question n'est pas valide et entraînerait le lancement de EXECUTE IMMEDIATE. Le SQL dynamique est difficile, notamment parce qu'il convertit les erreurs de compilation en erreurs d'exécution.