I have a question about stored procedures in Oracle.
Below is the stored procedure and tables as it stands:
create table STORES
(
ID number,
NAME varchar2(100),
CITY varchar2(100),
EXPIRES DATE
)
insert into stores values(1, 'Store 1', 'City 1', sysdate);
insert into stores values(2, 'Store 2', 'City 1', sysdate);
insert into stores values(3, 'Store 3', 'City 2', sysdate);
create table CLOSED
(
ID number,
NAME varchar2(100),
CITY varchar2(100)
)
create or replace PROCEDURE
pr_TestProc(subQuery IN VARCHAR2)
IS
begin
insert into CLOSED (ID, NAME, CITY)
select ID, NAME, CITY
from STORES
where ID in (1, 2, 3);
end;
What I’d like to do is replace the “in” values with the subQuery passed in as a parameter.
So if I run the procedure like:
execute pr_TestProc('select ID from STORES where EXPIRES <= sysdate');
The query passed in should be executed as a subquery being run inside the procedure.
Something like:
insert into CLOSED (ID, NAME, CITY) select ID, NAME, CITY
from STORES
where ID in (execute(subQuery));
Obviously this doesn’t work, but what would be the best way to achieve this, or is it even possible?
Thanks,
Brian
You can use dynamic SQL
If you are calling this procedure rarely in a system that is relatively idle, that will probably work acceptably well. If you are calling it frequently with different subqueries, however, you are going to generate a ton of non-sharable SQL statements. That will force Oracle to do a lot of hard parsing. It will also flood your shared pool with non-sharable SQL statements, likely forcing out plans that you want to be cached, forcing more hard parsing when those SQL statements are then executed again. And if you do it fast enough, you’re likely to end up getting errors (or causing other processes to get errors) that Oracle couldn’t allocate enough memory in the shared pool for a particular query. Plus, dynamic SQL is harder to write, harder to debug, vulnerable to SQL injection attacks, etc. so it generally makes the system harder to deal with.
A more elegant solution would be to pass in a collection rather than a subquery would be to pass in a collection