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: 無効な番号) が発生します。

print ステートメント'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_tableDOES のデータはこのプロセスによって削除されるため、データがother_table存在しないため参照することはできません。other_table.id後で親レコードを確認できるように、値を保存する方法が必要です。

4

5 に答える 5

6

other_table.idPL/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

この目的のためにグローバル一時テーブルを使用します

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

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

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 に答える