sql >> Database >  >> RDS >> Oracle

Hoe parameters te gebruiken in een 'where value in...'-clausule?

Het gebruik van dynamische SQL is de eenvoudigste benadering vanuit een coderingsstandpunt. Het probleem met dynamische SQL is echter dat je elke afzonderlijke versie van de query hard moet ontleden, wat niet alleen het potentieel heeft om je CPU te belasten, maar het potentieel heeft om je gedeelde pool te overspoelen met veel niet-deelbare SQL-instructies, waardoor out-instructies die u in de cache wilt opslaan, wat leidt tot meer harde parsen en fragmentatiefouten in de gedeelde pool. Als u dit eenmaal per dag uitvoert, is dat waarschijnlijk geen groot probleem. Als honderden mensen het duizenden keren per dag uitvoeren, is dat waarschijnlijk een grote zorg.

Een voorbeeld van de dynamische SQL-aanpak

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.

Als alternatief kunt u een verzameling gebruiken. Dit heeft het voordeel dat het een enkele, deelbare cursor genereert, zodat u zich geen zorgen hoeft te maken over het hard parseren of overstromen van de gedeelde pool. Maar het vereist waarschijnlijk wat meer code. De eenvoudigste manier om met collecties om te gaan

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.

Als je daarentegen echt moet beginnen met een door komma's gescheiden lijst met waarden, dan moet je die string in een verzameling ontleden voordat je hem kunt gebruiken. Er zijn verschillende manieren om een ​​begrensde tekenreeks te ontleden -- mijn persoonlijke favoriet is het gebruik van reguliere expressies in een hiërarchische zoekopdracht, maar je zou zeker ook een procedurele benadering kunnen schrijven

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.


  1. Beslis tussen controle op basis van agenten of controle zonder agenten

  2. Wat geeft parameters door aan SQL en waarom heb ik deze nodig?

  3. Postgres faalt met 'kon relatietoewijzingsbestand global/pg_filenode.map niet openen'

  4. Volledige deelname aan SQL