sql >> Database >  >> RDS >> Mysql

Oracle:Geparametriseerde query met IN-clausule retourneert null-waarde

U mag de door komma's gescheiden lijst doorgeven als parameter (bindvariabele), maar u bent verantwoordelijk voor het ontleden ervan in een subquery. Een oplossing gebaseerd op deze thread gebruikt regexp_substr.

CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHaR2, cur OUT sys_refcursor)
AS
BEGIN
open cur for  'with t1 as (select :A col from dual),
     t2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from t1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)
select col as id from t2' using A;
END;
/

De procedure is vereenvoudigd, maar zou een idee moeten geven hoe het te gebruiken.

Het grote voordeel ten opzichte van het gebruik van dynamische SQL (aaneenschakeling van strings) is dat u de instructie niet bij elke uitvoering hoeft te ontleden. Om nog maar te zwijgen over de beveiliging (angst voor SQL-injectie).

Gebruik:

DECLARE 
  l_cur SYS_REFCURSOR;
  l_id NUMBER;
BEGIN 
  p_getdata('1,1000,282828,4',l_cur);
 LOOP
    FETCH l_cur INTO l_id ;
    EXIT WHEN l_cur%NOTFOUND;
    dbms_output.put_line(l_id);
 END LOOP;
END;
/


1
1000
282828
4

UPDATE

De bovenstaande procedure is vereenvoudigd, om uw functionaliteit te krijgen, moet u een zoekopdracht als deze in de CURSOR gebruiken (d.w.z. splits eerst alle drie de parameters in afzonderlijke subquery's met behulp van subquery-factoring, pas dan de resultaten toe in uw query)

CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHAR2, B in VARCHAR2, c in VARCHAR2, cur OUT sys_refcursor)
AS
BEGIN
open cur for  'with ta1 as (select :A col from dual),
     ta2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from ta1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
 tb1 as (select :B col from dual),
     tb2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from tb1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
 tc1 as (select :C col from dual),
     tc2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from tc1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)              
select firstname, lastname, streetname, city
from mytable 
where zip IN (select col from ta2) AND 
      streetnumber IN (select col from tb2) AND 
      apt_num in (select col from tc2)' using A, B, C;
END;
/

test geslaagd

DECLARE 
  l_cur SYS_REFCURSOR;
  l_firstname VARCHAR2(20);
  l_lastname VARCHAR2(20);
  l_streetname VARCHAR2(20);
  l_city VARCHAR2(20);
BEGIN 
  p_getdata('1100,,1200','1,2','11,12' ,l_cur);
 LOOP
    FETCH l_cur INTO l_firstname, l_lastname, l_streetname, l_city;
    EXIT WHEN l_cur%NOTFOUND;
    dbms_output.put_line(l_firstname|| ' ' || l_lastname || ' ' || l_streetname  || ' ' || l_city);
 END LOOP;
END;
/


  1. Vouw een GROUP BY en HAVING resultatenset uit

  2. Entiteit in EF4 verwijderen zonder de hele entiteit te laden

  3. Invoegen met slaapstand native query werkt niet voor java.util.Date

  4. SQL FLOAT:3 punten die u zullen helpen rare rekenfouten te vermijden