Reputation: 1628
Using Oracle PL/SQL, how can I populate the bind variable :b3
with more than one value for the IN clause
? (This code is for demo purposes only -- it may not compile but it does clarify the question if any is needed)
declare
type work_rec is record (
work_status varchar2(50),
work_cd varchar2(50));
type work_tab is table of work_rec index by pls_integer;
t_work_tab work_tab;
sql_stmt varchar2(400);
begin
select case
when status_desc like '%Employed%' then 'Employed'
else 'Unknown'
end as work_status
,case
when status_cd between '1' and '9' then '1,2,3,4'
else '0'
end as work_cd
bulk collect into t_work_tab
from employee_table;
for i in t_work_tab.first..t_work_tab.last
loop
sql_stmt := 'insert into employee_hist
select name,
employer
from tax_table
where employment_cd in (:b3)'; --< how to populate this with '1','2','3','4'
execute immediate sql_stmt using t_work_tab(i).work_cd;
commit;
end loop;
end;
/
Upvotes: 0
Views: 2527
Reputation: 126
you could use a plsql collection as bind variable, this seems the nicer solution to me:
declare
type t_nbr_tbl is table of number;
type work_rec is record (
work_status varchar2(50),
work_cd t_nbr_tbl;
type work_tab is table of work_rec index by pls_integer;
t_work_tab work_tab;
sql_stmt varchar2(400);
begin
select case
when status_desc like '%Employed%' then 'Employed'
else 'Unknown'
end as work_status
,case
when status_cd between '1' and '9' then t_nbr_tbl(1,2,3,4)
else t_nbr_tbl(0)
end as work_cd
bulk collect into t_work_tab
from employee_table;
for i in t_work_tab.first..t_work_tab.last
loop
sql_stmt := 'insert into employee_hist
select name,
employer
from tax_table
where employment_cd in (select column_value from table(:b3))'; --< how to populate this with '1','2','3','4'
execute immediate sql_stmt using t_work_tab(i).work_cd;
commit;
end loop;
end;
/
Upvotes: 1
Reputation: 4538
You need to prepare the in list inside the loop using another variable and then the statement outside it. Something like this may help:
declare
type work_rec is record (
work_status varchar2(50),
work_cd varchar2(50));
type work_tab is table of work_rec index by pls_integer;
t_work_tab work_tab;
sql_stmt VARCHAR2(400);
v_in_str varchar2(100);_
begin
select case
when status_desc like '%Employed%' then 'Employed'
else 'Unknown'
end as work_status
,case
when status_cd between '1' and '9' then '1,2,3,4'
else '0'
end as work_cd
bulk collect into t_work_tab
from employee_table;
for i in t_work_tab.first..t_work_tab.last
loop
v_in_str := v_in_str || t_work_tab(i).work_cd || ',';
END loop;
v_in_str :=rtrim(v_in_str, ',');
sql_stmt := 'insert into employee_hist
select name,
employer
from tax_table
where employment_cd in ('||v_in_str||')';
execute immediate sql_stmt;
commit;
end;
Upvotes: 1
Reputation: 1628
Better solution (at least to my issue) - don't use a bind variable but instead concatenate the string of values (code segment shown only):
for i in t_work_tab.first..t_work_tab.last
loop
sql_stmt := 'insert into employee_hist
select name,
employer
from tax_table
where employment_cd in (' || t_work_tab(i).work_cd || ')';
execute immediate sql_stmt;
...
You get the idea. Thanks for all your input.
Upvotes: 0
Reputation: 291
When you loop through the values, keep appending the string with ' and , as required to make up the part of in. Then you can use that string as part of your sql statement.
Example
temp = "'"
Loop through values a,b,c,d as str
temp = temp + str + "'",
End Loop
temp = substr(temp,0,length(temp)) // this is to trim the last , character
Hope it helps!
Upvotes: 1