'using cursor inside cursor to loop through table values in oracle

I have a problem where I am trying to update a value of a table using another table through cursor.

create table A (product varchar2, loc varchar2, qty1 number s_date date);
insert into table A values('123','1',40,sysdate+2);
insert into table A values('123','1',50,sysdate+4);
insert into table A values('124','1',0,sysdate+2);
insert into table A values('124','1',0,sysdate+2);

create table B (p1 varchar2, p2 varchar2,loc2 varchar2, qty2 number, a_date date);
insert into table B values('123','124','1',30,sysdate+1);
insert into table B values('123','124','1',20,sysdate+2);
insert into table B values('123','124','1',50,sysdate+3);

Now the requirement is first sort A and B in ascending order of dates then

for p1 = product and loc2 = loc
    for p2 = product and loc2=loc
   if qty1>=qty2 and qty1>0 then
      qty1 = qty1-qty2 where product = p1
   else 
     move to next row of table A
       next.qty1 = qty1-(qty2-previous.qty1)

then we move on to next row of Table B and check if current qty1 from table A >0 and repeat the same process.I am using oracle 18c.

I am trying to acheive this by using 2 cursors but not really getting it. Is there any other way to implement this? can someone please help?



Solution 1:[1]

Here is a code that stores whole a and b table into a collection and makes your calculations with A.qty1 if the conditions are satisfied. I made at the end of the code a dbms_output.put_line of the A table collection because I m not sure I understood right your "pseudo code" where u describe conditions and calculation. Look up the server output and if the calculation done on A table collection are right it is easy to update a table with collection. Also note that this is not a very fast solution we are loading whole two tables into a collection (if your table A or B has million rows this will be executing forever) so try to use where in the select into clause to load only the rows u need for that update.

Sample data:

create table A (product varchar2(10), loc varchar2(10), qty1 number, s_date date);
insert into A values('123','1',40,sysdate+2);
insert into  A values('123','1',50,sysdate+4);

create table B (p1 varchar2(10), p2 varchar2(10),loc2 varchar2(10), qty2 

insert into  B values('123','124','1',30,sysdate+1);
insert into  B values('123','124','1',20,sysdate+2);

Pl/SQL code:

set SERVEROUTPUT ON;
declare
    type t_A_collection is table of a%rowtype index by pls_integer;
    v_A_collection t_A_collection;
    
    type t_B_collection is table of b%rowtype index by pls_integer;
    v_B_collection t_B_collection;
    
    v_previous_qty1 a.qty1%type;
begin
    select * bulk collect into v_A_collection from a order by s_date asc;
    select * bulk collect into v_B_collection from b order by a_date asc;
    
    for i in v_B_collection.first..v_B_collection.last loop
        --for j in v_A_collection.first..v_A_collection.last loop
      
            if v_A_collection.exists(i-1) then
                if v_B_collection(i).qty2>v_A_collection(i-1).qty1 then
                   v_A_collection(i).qty1:=v_A_collection(i).qty1-(v_B_collection(i).qty2-v_A_collection(i-1).qty1);
                    v_A_collection(i-1).qty1:=0;
                end if;
            else
                if v_B_collection(i).p1=v_A_collection(i).product
                and  v_B_collection(i).loc2=v_A_collection(i).loc then
                    v_A_collection(i).qty1:= abs(v_A_collection(i).qty1-v_B_collection(i).qty2);
                elsif v_B_collection(i).p2=v_A_collection(i).product then
                    v_A_collection(i).qty1:= abs(v_A_collection(i).qty1-v_B_collection(i).qty2);
                end if;
            end if;       
    end loop;
    for i in v_A_collection.first..v_A_collection.last loop
        dbms_output.put_line(v_A_collection(i).product||' '||v_A_collection(i).loc||' '||v_A_collection(i).qty1||' '||v_A_collection(i).s_date);
    end loop;
end;

Server output of collection for table A:

PRODUCT|LOC |QTY1 |S_DATE
-----------------------------
123     1    0     30.04.2022
123     1    40    02.05.2022

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1