Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie verwende ich Parameter in einer Klausel "wo Wert in ..."?

Die Verwendung von dynamischem SQL ist aus Codierungssicht der einfachste Ansatz. Das Problem mit dynamischem SQL ist jedoch, dass Sie jede einzelne Version der Abfrage hart parsen müssen, was nicht nur das Potenzial hat, Ihre CPU zu belasten, sondern auch Ihren gemeinsam genutzten Pool mit vielen nicht gemeinsam nutzbaren SQL-Anweisungen überfluten kann out-Anweisungen, die Sie zwischenspeichern möchten, was zu mehr harten Parses und Shared-Pool-Fragmentierungsfehlern führt. Wenn Sie dies einmal am Tag ausführen, ist das wahrscheinlich kein großes Problem. Wenn Hunderte von Menschen es tausendmal am Tag ausführen, ist das wahrscheinlich ein großes Problem.

Ein Beispiel für den dynamischen SQL-Ansatz

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.

Alternativ können Sie eine Sammlung verwenden. Dies hat den Vorteil, dass ein einzelner, gemeinsam nutzbarer Cursor generiert wird, sodass Sie sich keine Gedanken über eine harte Analyse oder eine Überflutung des gemeinsam genutzten Pools machen müssen. Aber es erfordert wahrscheinlich ein bisschen mehr Code. Der einfachste Weg, mit Sammlungen umzugehen

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.

Wenn Sie andererseits wirklich mit einer durch Kommas getrennten Liste von Werten beginnen müssen, müssen Sie diese Zeichenfolge in eine Sammlung zerlegen, bevor Sie sie verwenden können. Es gibt verschiedene Möglichkeiten, eine Zeichenfolge mit Trennzeichen zu parsen – mein persönlicher Favorit ist die Verwendung regulärer Ausdrücke in einer hierarchischen Abfrage, aber Sie könnten sicherlich auch einen prozeduralen Ansatz schreiben

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.