Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

executar consulta SQL armazenada em uma tabela


Este parece um requisito muito peculiar e difícil de resolver de forma robusta. STMT_OR_VALUE é a incorporação do antipadrão One Column Two Usages. Além disso, resolver STMT_OR_VALUE requer lógica de controle de fluxo e o uso de SQL dinâmico. Consequentemente, não pode ser uma solução SQL pura:você precisa usar PL/SQL para montar e executar a consulta dinâmica.

Aqui está uma prova de conceito para uma solução. Eu optei por uma função que você pode chamar do SQL. Depende de uma suposição:cada string de consulta inserida em TEST1.STMT_OR_VALUE tem uma projeção de uma única coluna numérica e cada string de valor é um CSV somente de dados numéricos . Com esta condição, é simples construir uma função que execute uma consulta dinâmica ou tokenize a string em uma série de números; ambos são coletados em massa em uma tabela aninhada:
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;
/

Observe que há mais de uma maneira de executar uma instrução SQL dinâmica e uma multiplicidade de maneiras de tokenizar um CSV em uma série de números. Minhas decisões são arbitrárias:sinta-se à vontade para substituir seus métodos preferidos aqui.

Esta função pode ser invocada com um table() ligar:
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
/

O grande benefício dessa abordagem é que ela encapsula a lógica em torno da avaliação de STMT_OR_VALUE e oculta o uso de SQL dinâmico. Conseqüentemente, é fácil empregá-lo em qualquer instrução SQL, mantendo a legibilidade, ou adicionar outros mecanismos para gerar um conjunto de IDs.

No entanto, esta solução é frágil. Só funcionará se os valores no test1 mesa obedeça as regras. Ou seja, não apenas eles devem ser conversíveis em um fluxo de números únicos, mas as instruções SQL devem ser válidas e executáveis ​​por EXECUTE IMMEDIATE. Por exemplo, o ponto e vírgula à direita nos dados de amostra da pergunta é inválido e faria com que EXECUTE IMMEDIATE fosse lançado. O SQL dinâmico é difícil, principalmente porque converte erros de compilação em erros de tempo de execução.