Question

Je définis une variable de liaison dans un bloc PL/SQL et j'essaie de l'utiliser dans l'expression IN d'une autre requête.Quelque chose comme ça:

variable x varchar2(255)

declare
    x varchar2(100);
begin
    for r in (select id from other_table where abc in ('&val1','&val2','&val3') ) loop
    x := x||''''||r.id||''',';
    end loop;
    --get rid of the trailing ','
    x:= substr(x,1,length(x)-1);

    select x into :bind_var from dual;
end;
/

print :bind_var;

select *
from some_table
where id in (:bind_var);

Et j'obtiens une erreur (ORA-01722 :Numéro invalide) sur la requête qui tente d'utiliser la variable de liaison dans la liste "IN".

La déclaration d'impression donne '123','345' c'est ce à quoi je m'attends.

Est-il possible d'utiliser la variable de liaison comme celle-ci ou dois-je essayer une approche différente ?

(avec Oracle 10g)


Clarification:

C'est pour une sorte de réconciliation.je veux courir

select *
from some_table
where id in (select id from other_table where abc in ('&val1','&val2','&val3'))

avant que la partie principale du script (non illustrée ici) ne supprime tout un tas d'enregistrements.Je veux le réexécuter ensuite pour vérifier que les enregistrements dans some_table n’ont PAS été supprimés.Cependant, les données dans other_table EST supprimé par ce processus, je ne peux donc pas simplement me référer aux données contenues dans other_table parce qu'il n'y a rien là-bas.J'ai besoin d'un moyen de préserver le other_table.id valeurs afin que je puisse vérifier les enregistrements parents par la suite.

Était-ce utile?

La solution

je stockerais le other_table.idse trouve dans une table PL/SQL et référencez ensuite cette table dans la requête :

type t_id_table is table OF other_table.id%type index by binary_integer;
v_table t_id_table;

-- fill the table
select id
bulk collect into v_table
from other_table 
where abc in ('&val1','&val2','&val3');     

-- then at a later stage...    

select *
from some_table st
,    table(cast(v_table AS t_id_table)) idt
where st.id = idt.id;

Autres conseils

Vous ne pouvez pas utiliser de valeurs séparées par des virgules dans une variable de liaison.

Tu pourrais dire:

select * from some_table where id in (:bind_var1, :bind_var2)

cependant

Il vaut mieux utiliser quelque chose comme :

select * from some_table where id in ("select blah blah blah...");

J'utiliserais une table temporaire globale à cet effet

create global temporary table gtt_ids( id number ) ;

alors

...
for r in (select id from other_table where ... ) loop
   insert into gtt_ids(id) values (r.id) ;
end loop;
...

et à la fin

select *
from some_table
where id in (select id from gtt_ids);

Ok, j'ai une sorte de solution moche qui utilise aussi des variables de substitution...

col idList NEW_VALUE v_id_list /* This is NEW! */
variable x varchar2(255)
declare
    x varchar2(100);
begin
    for r in (select id from other_table where abc in ('&val1','&val2','&val3') ) loop
    x := x||''''||r.id||''',';
    end loop;
    --get rid of the trailing ','
    x:= substr(x,1,length(x)-1);

    select x into :bind_var from dual;
end;
/

print :bind_var;

select :x idList from dual;  /* This is NEW! */

select *
from some_table
where id in (&idList);  /* This is CHANGED! */

Cela fonctionne, mais j'accepterai une réponse de quelqu'un d'autre si elle est plus élégante.

changé la boucle à utiliser liste (malheureusement, cela ne fonctionnera qu'en 11gr2).

mais pour la variable dans la liste, j'ai utilisé un expression régulière pour atteindre l'objectif (mais avant 10 g, vous pouvez utiliser sous-titre pour faire de même), ceci est tiré de la question posée liée.

    variable bind_var varchar2(255)
variable dataSeperationChar varchar2(255)

declare
    x varchar2(100);
begin

select listagg(id,',')  within group(order by id) idList
into x
  from(select level id 
         from dual  
        connect by level < 100 ) 
where id in (&val1,&val2,&val3) ;
    select x into :bind_var from dual;
    :dataSeperationChar := ',';
end;
/

print :bind_var;

/



select *
  from (
        select level id2
          from dual
         connect by level < 100
        )
    where id2 in(
            select  -- transform the comma seperated string into a result set        
            regexp_substr(:dataSeperationChar||:bind_var||','
                        , '[^'||:dataSeperationChar||']+'
                      ,1
                      ,level)    as parsed_value
            from dual
            connect by level <= length(regexp_replace(:bind_var, '([^'||:dataSeperationChar||'])', '')) + 1    
    )
;

/*
values of 1,5, and 25

BIND_VAR
------
1,5,25

ID2                    
---------------------- 
1                      
5                      
25   
*/

MODIFIER


Oups je viens de remarquer que tu as marqué 10g, la seule chose à faire est de NE PAS utiliser le listagg que j'ai fait au début

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top