sql >> Base de Datos >  >> RDS >> Oracle

ejecutar consulta SQL almacenada en una tabla

Este parece un requisito muy peculiar, y que será difícil de resolver de manera sólida. STMT_OR_VALUE es la realización del antipatrón Una columna, dos usos. Además, resolver STMT_OR_VALUE requiere lógica de control de flujo y el uso de SQL dinámico. En consecuencia, no puede ser una solución SQL pura:necesita usar PL/SQL para ensamblar y ejecutar la consulta dinámica.

Aquí hay una prueba de concepto para una solución. He optado por una función a la que puede llamar desde SQL. Depende de una suposición:cada cadena de consulta que inserte en TEST1.STMT_OR_VALUE tiene una proyección de una sola columna numérica y cada cadena de valor es un CSV solo de datos numéricos . Con esta condición, es sencillo construir una función que ejecute una consulta dinámica o tokenice la cadena en una serie de números; ambos se recopilan de forma masiva en una tabla anidada:

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

Tenga en cuenta que hay más de una forma de ejecutar una instrucción SQL dinámica y una multiplicidad de formas de tokenizar un CSV en una serie de números. Mis decisiones son arbitrarias:siéntete libre de sustituir tus métodos preferidos aquí.

Esta función se puede invocar con una table() llamar:

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
/

El gran beneficio de este enfoque es que encapsula la lógica en torno a la evaluación de STMT_OR_VALUE y oculta el uso de Dynamic SQL. En consecuencia, es fácil emplearlo en cualquier instrucción SQL manteniendo la legibilidad, o agregar más mecanismos para generar un conjunto de ID.

Sin embargo, esta solución es frágil. Solo funcionará si los valores en test1 mesa obedecer las reglas. Es decir, no solo deben ser convertibles a un flujo de números únicos, sino que las sentencias SQL deben ser válidas y ejecutables por EXECUTE IMMEDIATE. Por ejemplo, el punto y coma final en los datos de muestra de la pregunta no es válido y haría que EJECUTAR INMEDIATO se lanzara. El SQL dinámico es difícil, sobre todo porque convierte los errores de compilación en errores de tiempo de ejecución.