3

我在 PL/SQL 块中设置了一个绑定变量,并试图在另一个查询的 IN 表达式中使用它。像这样的东西:

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);

我在尝试使用“IN”列表中的绑定变量的查询中收到错误(ORA-01722:无效号码)。

打印语句的结果'123','345'是我所期望的。

是否可以像这样使用绑定变量,还是应该尝试不同的方法?

(使用 Oracle 10g)


澄清:

这是为了和解之类的事情。我想跑

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

在脚本的主要部分(此处未显示)删除一大堆记录之前。之后我想再次运行它以验证其中的记录some_table是否未被删除。但是,other_table此过程确实删除了中的数据,因此我不能仅引用其中的数据,other_table因为那里什么都没有。我需要一种方法来保留这些other_table.id值,以便以后可以验证父记录。

4

5 回答 5

6

我会将other_table.id's 存储在 PL/SQL 表中,然后在查询中引用该表:

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;
于 2011-02-11T21:37:57.987 回答
1

您不能在一个绑定变量中使用逗号分隔值。

你可以说:

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

尽管

你最好使用类似的东西:

select * from some_table where id in ("select blah blah blah...");
于 2011-02-11T20:44:39.020 回答
1

我会为此目的使用一个全局临时表

create global temporary table gtt_ids( id number ) ;

然后

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

最后

select *
from some_table
where id in (select id from gtt_ids);
于 2011-02-11T21:38:10.700 回答
1

将循环更改为使用listagg(遗憾的是,这仅适用于 11gr2)。

但是对于列表中的变量,我使用正则表达式来实现目标(但在 10g 之前,您可以使用substr来做同样的事情)这是从链接的 asktom 问题中提取的。

    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   
*/

编辑


糟糕,刚刚注意到您确实标记了 10g,唯一要做的就是不要使用我在开始时所做的 listagg

于 2011-02-11T21:48:54.777 回答
0

好的,我有一种丑陋的解决方案,它也使用替换变量......

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! */

它有效,但如果它更优雅,我会接受其他人的回答。

于 2011-02-11T21:14:46.457 回答