Reputation: 15
procedure new_cust (p_practiceid varchar2)is
custid varchar2(255);
l_error_stack varchar2(4000);
l_error_code integer;
cursor c1 is select id
from customers
where joining_date = to_char(sysdate,'YYYY-MM');
begin
OPEN c1;
loop
FETCH c1 INTO custid;
EXIT WHEN c1%NOTFOUND;
begin
execute immediate 'drop table new_clients';
execute immediate 'create table new_clients as select * from client_names where custid= '''||custid||'''';
exception when others then
l_error_stack := substr(dbms_utility.format_error_backtrace,1,2500)||chr(10)||substr(dbms_utility.format_error_stack,1,500) ;
l_error_code := sqlcode;
daily_check_log.logger(systimestamp, inPracticeId, 'error', 'new_cust', l_error_code, l_error_stack);
end;
END LOOP;
CLOSE c1;
end;
I am using a cursor to determine new clients that joined this month. There should be at least 10 new records but the cursor is returning just 1 row. Where am I going wrong?
Upvotes: 0
Views: 256
Reputation: 142705
In my opinion, the whole concept is wrong. In Oracle, you don't create table dynamically, there are really, really rare situations which justify that. Your code is completely static, there's nothing that requires dynamic SQL.
Consider creating a table, once - and reuse it as needed. It might involve deleting rows from it.
CTAS with a false condition will create an empty table:
create table new_clients as select * from client_names where 1 = 2;
Insert data into it on a monthly basis (as that's what your code suggests):
insert into new_clients
select *
from client_names
where custid in (select id
from customers
where joining_date between trunc(sysdate, 'mm')
and trunc(last_day(sysdate))
);
I suppose that JOINING_DATE isn't really YYYY-MM but a true date. If there's an index on it, it'll still work because of the BETWEEN clause which fetches the whole current month (though, it might need further adjustment, depending on data you have).
Also, it would be better if you specified column names involved in the INSERT statement (doesn't matter if there are lot of them - name them, all, one by one). select *
works fine until something changes, and then it works not.
If necessary such an insert
can be easily moved into a procedure. Speaking of which: what's the IN parameter used for? You declared it, but it's never used.
Upvotes: 0
Reputation: 4538
You don't have to create a cursor for this simple task, this code should be ok for your requirement
procedure new_cust (p_practiceid varchar2) is
begin
execute immediate 'drop table new_clients';
execute immediate 'create table new_clients as
select cn.*
from client_names cn
join customers c
on c.id = cn.custid
where c.joining_date = to_char(sysdate,''YYYY-MM'')';
end;
And don't forget to put exception handling in it :)
Upvotes: 1