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

Como usar parâmetros em uma cláusula 'where value in...'?


Usar SQL dinâmico é a abordagem mais simples do ponto de vista de codificação. O problema com o SQL dinâmico, no entanto, é que você precisa analisar cada versão distinta da consulta que não apenas tem o potencial de sobrecarregar sua CPU, mas tem o potencial de inundar seu pool compartilhado com muitas instruções SQL não compartilháveis, empurrando out que você gostaria de armazenar em cache, causando mais análises difíceis e erros de fragmentação de pool compartilhado. Se você estiver executando isso uma vez por dia, provavelmente não é uma grande preocupação. Se centenas de pessoas estão executando milhares de vezes por dia, isso provavelmente é uma grande preocupação.

Um exemplo da abordagem SQL dinâmica
SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_deptnos  varchar2(100) := '10,20';
  3    l_rc       sys_refcursor;
  4    l_dept_rec dept%rowtype;
  5  begin
  6    open l_rc for 'select * from dept where deptno in (' || l_deptnos || ')';
  7    loop
  8      fetch l_rc into l_dept_rec;
  9      exit when l_rc%notfound;
 10      dbms_output.put_line( l_dept_rec.dname );
 11    end loop;
 12    close l_rc;
 13* end;
SQL> /
ACCOUNTING
RESEARCH

PL/SQL procedure successfully completed.

Como alternativa, você pode usar uma coleção. Isso tem a vantagem de gerar um cursor único e compartilhável para que você não precise se preocupar com análise difícil ou inundação do pool compartilhado. Mas provavelmente requer um pouco mais de código. A maneira mais simples de lidar com coleções
SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_deptnos  tbl_deptnos := tbl_deptnos(10,20);
  3  begin
  4    for i in (select *
  5                from dept
  6               where deptno in (select column_value
  7                                  from table(l_deptnos)))
  8    loop
  9      dbms_output.put_line( i.dname );
 10    end loop;
 11* end;
SQL> /
ACCOUNTING
RESEARCH

PL/SQL procedure successfully completed.

Se, por outro lado, você realmente tiver que começar com uma lista de valores separados por vírgulas, terá que analisar essa string em uma coleção antes de poder usá-la. Existem várias maneiras de analisar uma string delimitada - minha favorita é usar expressões regulares em uma consulta hierárquica, mas você certamente também pode escrever uma abordagem procedural
SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_deptnos     tbl_deptnos;
  3    l_deptno_str  varchar2(100) := '10,20';
  4  begin
  5    select regexp_substr(l_deptno_str, '[^,]+', 1, LEVEL)
  6      bulk collect into l_deptnos
  7      from dual
  8   connect by level <= length(replace (l_deptno_str, ',', NULL));
  9    for i in (select *
 10                from dept
 11               where deptno in (select column_value
 12                                  from table(l_deptnos)))
 13    loop
 14      dbms_output.put_line( i.dname );
 15    end loop;
 16* end;
 17  /
ACCOUNTING
RESEARCH

PL/SQL procedure successfully completed.