I have a table with employees and for each employees have few bills. I declare 2 cursors, one for all employees(distinct) and second cursor for all bills for one employees. Now, open 1st cursor with all employees, fetch one, open second cursor (based on employee from 1st cursor) with all bills for employee. To reuse a second cursor for all employees, I open and close second cursor for each employee. This thing spend a lot of time. How to reuse a second cursor instead reopen or any good idea?
Part of code in Pro*C:
struct sforc1 {
long nis_rad[ROWS_FETCHED_C1];
long sec_nis[ROWS_FETCHED_C1];
/*char f_fact[9];
long sec_rec;*/
}forc1;
struct sforc2 {
long nis_rad[ROWS_FETCHED_C2];
long sec_nis[ROWS_FETCHED_C2];
char f_fact[ROWS_FETCHED_C2][9];
long sec_rec[ROWS_FETCHED_C2];
char f_p_camb_est[ROWS_FETCHED_C2][9];
char op_cambest[ROWS_FETCHED_C2][9];
}forc2;
void main (void)
{
exec sql declare c1 cursor for
select distinct nis_rad, sec_nis
from recibos
where ((imp_tot_rec - imp_cta)>0) and f_p_camb_est = '29991231';
exec sql declare c2 cursor for
select nis_rad, sec_nis, f_fact, sec_rec, f_p_camb_est, op_cambest
from recibos
where ((imp_tot_rec - imp_cta)>0) and f_p_camb_est = '29991231' and nis_rad = :forc1.nis_rad[i] and sec_nis=:forc1.sec_nis[i];
exec sql open c1;
while(1){
exec sql fetch c1 into :forc1;
rows_this_time1 = sqlca.sqlerrd[2]-rows_before1;
rows_before1 = sqlca.sqlerrd[2];
if (rows_this_time1==0){
break;
}
for(i=0;i<rows_this_time1;++i){
exec sql open c2;
rows_before2 = 0;
while(1){
exec sql fetch c2 into :forc2;
rows_this_time2 = sqlca.sqlerrd[2]-rows_before2;
rows_before2=sqlca.sqlerrd[2];
if(rows_this_time2==0){
break;
}
for(j=0;j<rows_this_time2;++j){
strcpy(forc2.f_p_camb_est[j], "20161212");
strcpy(forc2.op_cambest[j], "SIMD0943");
}
EXEC SQL
update recibos
set f_p_camb_est = :forc2.f_p_camb_est,
op_cambest = :forc2.op_cambest
where nis_rad = :forc2.nis_rad
and sec_nis = :forc2.sec_nis
and f_fact = :forc2.f_fact
and sec_rec = :forc2.sec_rec;
}
exec sql close c2;
}
exec sql close c1;
exec sql commit;
exec sql open c1;
rows_before1 = 0;
}
exec sql close c1;
}
nis_rad and sec_nis is a employee_id(primary key). Each nis_rad have few bills f_fact(bills)
For processing 10000 nis_rad's spend 30 min, and 28-29 min is for re-open second cursor(c2)
UP. Deleted previously example
I've edited an answer.
You can't reuse date from cursor without opening it again unless you cache all results in memory. Cursor is like pointer to data when you read record it already points to next so you can't get back.
Problem in your code is using SQL imperative way. You shouldn't pull all records to your application and then apply logic. Think about how to write a query that will return only records you need to process. It may be even faster to execute 2-3 queries that will return records for each section of your code than pull all data and then check logic in application.