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
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.