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

¿Cómo usar parámetros en una cláusula 'where value in...'?

El uso de SQL dinámico es el enfoque más simple desde el punto de vista de la codificación. Sin embargo, el problema con el SQL dinámico es que tiene que analizar cada versión distinta de la consulta, lo que no solo tiene el potencial de gravar su CPU, sino que también tiene el potencial de inundar su grupo compartido con muchas declaraciones SQL no compartibles, empujando out declaraciones que le gustaría almacenar en caché, lo que provoca más análisis duros y errores de fragmentación del grupo compartido. Si está ejecutando esto una vez al día, probablemente no sea una preocupación importante. Si cientos de personas lo ejecutan miles de veces al día, es probable que sea una gran preocupación.

Un ejemplo del enfoque de SQL dinámico

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.

Alternativamente, puede usar una colección. Esto tiene la ventaja de generar un solo cursor compartible para que no tenga que preocuparse por el análisis duro o la inundación del grupo compartido. Pero probablemente requiera un poco más de código. La forma más sencilla de gestionar los cobros

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.

Si, por otro lado, realmente tiene que comenzar con una lista de valores separados por comas, entonces tendrá que analizar esa cadena en una colección antes de poder usarla. Hay varias formas de analizar una cadena delimitada:mi favorito personal es usar expresiones regulares en una consulta jerárquica, pero ciertamente también podría escribir un enfoque de procedimiento

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.