Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

SQL cursor take too long to complete

DECLARE
  orderid NUMBER;
  customerid NUMBER;
  channel VARCHAR2(20);
  amount NUMBER;

  CURSOR orders_cursor IS
    SELECT
      order_id,
      customer_id,
      channel,
      FINAL_PROFIT(order_id) AS amount
    FROM temp_orders
     FOR UPDATE ;
BEGIN
  OPEN orders_cursor;
    LOOP
    FETCH orders_cursor INTO orderid, customerid, channel, amount;
    EXIT WHEN orders_cursor%NOTFOUND;

    IF amount < 0 THEN
      INSERT INTO deficit (orderid, customerid, channel, amount)
        VALUES (orderid, customerid, channel, -amount);
    ELSE
      INSERT INTO profit (orderid, customerid, channel, amount)
        VALUES (orderid, customerid, channel, amount);
    END IF;
  END LOOP;
  CLOSE orders_cursor;
END;

I have this cursor that takes order_id,customer_id,channel and a value from the function FINAL_PROFIT and then checks if amount is positive or negative and puts it in the rigth table .The cursor Works but it takes way to long to complete(30+minutes).I need it to be faster.
This is the FINAL_PROFIT function

create or replace FUNCTION FINAL_PROFIT (o_id NUMBER)
RETURN NUMBER 
IS  
    f_profit FLOAT := 0;
    v_delay NUMBER := 0;
BEGIN
    v_delay := MAX_DELAY(o_id);

    SELECT SUM(o.price - o.cost - (v_delay * (0.001 * TO_NUMBER(p.list_price,'9999.99')))) as FINAL_PROFT
    INTO f_profit  
    FROM ORDERS o 
    JOIN PRODUCTS p ON o.product_id = p.product_id 
    WHERE o_id = o.order_id
    GROUP BY o_id ;
    
    RETURN f_profit;  
END FINAL_PROFIT;

I tried FOR UPDATE because i thougth would make it faster but i didnt notice any diference in time

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

There’s so very few times you’ll encounter a need to run SQL inside of a loop that you can pretty much just make it a rule that if you find yourself thinking "I can run this SQL in a loop" to immediately think "so I must be thinking about this wrong".

Instead, two insert statements will take care of this:

INSERT INTO deficit (orderid, customerid, channel, amount)
SELECT
  order_id,
  customer_id,
  channel,
  FINAL_PROFIT(order_id) * -1 AS amount
FROM temp_orders
WHERE amount < 0;

INSERT INTO deficit (orderid, customerid, channel, amount)
SELECT
  order_id,
  customer_id,
  channel,
  FINAL_PROFIT(order_id) AS amount
FROM temp_orders
WHERE amount >= 0

Likely that function can be changed as well to just be part of your SQL so you aren’t calling a sql function over and over and over again as well.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading