2013-03-03 3 views
3

J'utilise une procédure stockée pour sélectionner des enregistrements à l'aide d'un curseur. Cette procédure obtient l'ID d'enregistrement en entrée.Requête dynamique dans la procédure Oracle à l'aide du curseur

Voici le code:

create or replace 
procedure GET_ITEM_DETAILS_ALL 
(
    cur_out out sys_refcursor, 
    PSTRING VARCHAR2 DEFAULT NULL 
) 
is 
    query_string VARCHAR2(1000); 
Begin 
    query_string := 'Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (:sl) order by IT.SL_NO'; 
    OPEN cur_out FOR query_string USING PSTRING; 
End; 

Et pour appeler/tester la procédure que j'utilise le code ci-dessous:

VAR R REFCURSOR 
EXEC GET_ITEM_DETAILS_ALL (:R, '4') 
PRINT R 

Le problème est quand je passe un seul numéro entier tel que « 4 'ou' 2 ', la procédure retourne des données, mais quand je passe' 1,2 'ou' 3,4 ', elle montre une erreur.

Répondre

0

Le problème est que PSTRING est une variable unique et non un tableau. Donc, votre déclaration équivaut en fait à

.... where IT.SL_NO = PSTRING 

Voilà pourquoi cela fonctionne lorsque vous passez 4 et échoue où vous passez 1,2. Vous n'avez aucune valeur en utilisant SQL dynamique comme vous le faites (nous pouvons ouvrir le curseur ref sans utiliser de chaînes). Cependant, en profitant de SQL dynamique est une façon de résoudre votre problème:

query_string := 'Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (' 
        ||PSTRING|| 
        ') order by IT.SL_NO'; 
OPEN cur_out FOR query_string; 

Vous pouvez également utiliser une chaîne tokenizer pour transformer la chaîne en bien, en jetons. Malheureusement, Oracle ne dispose pas d'un standard intégré, mais il existe plusieurs solutions de contournement pour différentes versions de la base de données. Adrian Billington a a good round-up on his site. L'utilisation d'un de ces approches permet d'abandonner le SQL dynamique:

OPEN cur_out FOR select IT.SL_NO from ITEM_DETAILS IT 
    where IT.SL_NO in (select * from table (your_string_tokenizer(PSTRING))) 
    order by IT.SL_NO; 
0

Vous ne pouvez pas transmettre une liste de valeurs à une requête à l'aide d'une variable de liaison.
Après avoir transmis une chaîne avec une liste séparée par des virgules, votre requête devient
Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in ('1,2') order by IT.SL_NO
ce qui est incorrect.
Vous devez convertir manuellement la chaîne d'entrée en une liste de valeurs dans votre requête.

0

La solution est donnée ci-dessous:

create or replace procedure GETITEM_DETAILS_ALL 

(
    cur_out out sys_refcursor, 
    PSTRING VARCHAR2 DEFAULT NULL 
) 

is 

query_string VARCHAR2(1000); 

Begin 

query_string := 'Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (' || PSTRING || ') order by IT.SL_NO'; 

OPEN cur_out FOR query_string; 

End; 
1
OPEN cur_out FOR Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (SELECT REGEXP_SUBSTR(sl,'[^,]+', 1, LEVEL) FROM DUAL CONNECT BY REGEXP_SUBSTR(sl, '[^,]+', 1, LEVEL) IS NOT NULL) order by IT.SL_NO 
Questions connexes