cursor within a trigger - mysql

I am trying to make a cursor inside a trigger and the result of the cursor allows me to make inserts in another table, but I have problems with the NEW.id, I think that when I entered the cursor this parameter became empty .. how could it fix it?
when I send a static data it works without problem
I appreciate your help.
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE _ingredient_id INTEGER;
DECLARE _unit_cost decimal(11,2);
DECLARE _quantity INTEGER;
DECLARE items CURSOR FOR
SELECT ingredients.id,ingredients.unit_cost,recipes.quantity
FROM sales, orders,detail_orders,recipes,ingredients
WHERE sales.id = NEW.id
AND orders.sale_id= NEW.id
AND detail_orders.order_id=orders.id
AND detail_orders.food_id=recipes.food_id
AND recipes.ingredient_id=ingredients.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN items;
getItems: LOOP
FETCH items INTO _ingredient_id,_unit_cost,_quantity;
IF finished = 1 THEN
LEAVE getItems;
END IF;
SET #total= _unit_cost*_quantity;
INSERT INTO inventories (type,date,ingredient_id,quantity,unit_cost,total,sale_id) VALUES (2,now(),_ingredient_id,_quantity,_unit_cost,#total,NEW.id);
END LOOP getItems;
CLOSE items;
END

I managed to solve the problem with a stored procedure

Related

CURSOR MYSQL TRIGGER

It's the first time I use cursors and im having issues with the variable 'done'. This variable handles whether the loop iterates over the cursosr or not. When the trigger its executed, the following error happens:
ERROR 1193 (HY000): Unknown system variable 'done'
As far as i see in the mysql cursor documentation, the 'done' variable declaration is correct. Anyone sees the problem?
The trigger:
delimiter //
CREATE TRIGGER `prestamo_positivo` AFTER UPDATE ON `prestamo`
FOR EACH ROW BEGIN
DECLARE aux VARCHAR(10);
DECLARE aux2 CHAR(10);
DECLARE c1 CURSOR FOR SELECT id_cliente FROM PRESTATARIO;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET aux=(SELECT A.id_cliente FROM PRESTATARIO A, PRESTAMO B WHERE A.numero_prestamo=OLD.numero);
IF(NEW.cantidad = 0) THEN
DELETE FROM `prestamo` WHERE numero=OLD.numero;
OPEN c1;
c1_loop: LOOP
fletch c1 into aux2;
IF done THEN LEAVE c1_loop; END IF;
IF(aux = aux2) THEN
INSERT INTO `mensaje`(mensaje, id_usuario) VALUES ("Renegociar prestamos del cliente",aux);
END IF;
END LOOP c1_loop;
CLOSE c1;
END IF;
END; //
If you check the sample code you linked in the question, you can see that done variable is explicitly declared before the continue handler, so you need to do the same. The below excerpt is from the sample code from the link you specified:
DECLARE done INT DEFAULT FALSE; //<= declare done variable here
DECLARE a CHAR(16);
DECLARE b, c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
Also, as P.Salmon has already remarked, you cannot modify the table the trigger is declared on, therefore
DELETE FROM `prestamo` WHERE numero=OLD.numero;
line will fail with error 1442.

Why MySQL Cursor stopped looping while reporting a success

I created a procedure as below in MySQL workbench 8.0.12 community, win10. A cursor is declared to loop through more than 16000 member's ID in a table to insert their number of orders created in different dates into another table.
Member's IDs and their dates of registration are selected here for the cursor. select distinct BAG,AAA from DICT_ALLE_AAAF where AAA>=Date_Memb_Star. Once I call it call PRO_MIDD_MEMB_AAAA_1('2017/01/01','2019/11/10',60), it only looped through 5 member's IDs and did not report any error. But if I took the while loop out of the procedure and with select Var_BAG on, the cursor loop went selecting more than 200 member's IDs until it asked me to cancel it. Can anyone tell me what is wrong in my code? Many thanks.
delimiter //
create procedure PRO_MIDD_MEMB_AAAA_1
(in Date_Memb_Star date,
in Date_Sale_End date,
in Int_Inte int)
begin
declare Int_Floo int default 0;
declare Int_Ceil int;
declare Int_MembAll int;
declare Int_Loop int default 1;
declare Int_MaxiLoop int;
declare Int_DaySpen int default 30;
declare Int_Done int;
declare Var_BAG varchar(16);
declare Date_Memb_Regi date;
declare Cur_Memb cursor for
select distinct BAG,AAA from DICT_ALLE_AAAF where AAA>=Date_Memb_Star order by BAG;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET Int_Done = 1;
truncate table MIDD_MEMB_AAAA;
open Cur_Memb;
read_loop:loop
fetch Cur_Memb into Var_BAG,Date_Memb_Regi;
if Int_Done=1 then
leave read_loop;
end if;
/*select Var_BAG;*/
set Int_MaxiLoop=ceil(datediff(Date_Sale_End,Date_Memb_Regi)/Int_Inte);
set Int_Floo=0;
while Int_Loop<=Int_MaxiLoop do
set Int_Ceil=Int_Floo+Int_Inte;
insert into MIDD_MEMB_AAAA
select Var_BAG,Int_Floo,Int_Ceil,
count(distinct BAK)*(Int_DaySpen/Int_Inte) as Numb_Con_Avg
from OPER_SALE_AAAB
where BAG=Var_BAG
and timestampdiff(hour,Date_Memb_Regi,AAA)/24>Int_Floo
and timestampdiff(hour,Date_Memb_Regi,AAA)/24<=Int_Ceil
and AAB>0;
set Int_Floo=Int_Floo+Int_Inte;
set Int_Loop=Int_Loop+1;
end while;
end loop read_loop;
close Cur_Memb;
end//
delimiter ;
Little oversight: you forgot to reset your variable Int_Loop, so after the first run, it only enters the loop when Int_MaxiLoop has a new maximum value.
Reinitialize it (to 1, I assume) before the loop:
...
set Int_Floo=0;
set Int_Loop=1;
while Int_Loop<=Int_MaxiLoop do ...

mysql 5.7 cursor not returning any values

Mysql (version 5.7) cursor not working. I tried many times and checked online could not find what is wrong.
It is looping through correctly as many records in the currency table. But when I try to read from the cursor it is only returning null and not the actual values from the table currency. The currency table has data.
DROP PROCEDURE IF EXISTS proc2;
CREATE PROCEDURE proc2()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE code VARCHAR(255);
DECLARE myCursor CURSOR FOR SELECT code FROM currency;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN myCursor;
delete from dummy;
read_loop: LOOP
FETCH myCursor INTO code;
IF finished = 1 THEN
LEAVE read_loop;
END IF;
insert into dummy(name) values(code);
END LOOP read_loop;
CLOSE myCursor;
End;
At last, it worked with below change to the script. (i.e. after adding table alias.)
For some reason, the column I tried out 'code' expects an alias. Maybe a reserved keyword, not sure.
DECLARE myCursor CURSOR FOR SELECT c.code FROM currency c;

what is wrong in this mysql cursor, and how to correct it?

CREATE PROCEDURE curLike()
BEGIN
DECLARE likeRec likecounttable;
DECLARE c_likeCount CURSOR FOR SELECT l.likeCount, l.qId FROM likecounttable l;
OPEN c_likeCount;
start_loop:LOOP
FETCH c_likeCount IN likeRec
UPDATE qentry SET qentry.likeCount = likeRec.likeCount WHERE qentry.qId=likeRec.qId;
END LOOP;
CLOSE c_likeCount;
END;
I am trying to use a cursor here which fetches records from likecounttable, I saw this type of syntax in few sites so I used it but it is not working
You are missing a semi-colon after your first declaration, furthermore, likecounttable is a table, not a data type.
Since you're trying to store two column values into your declared variables, your first line should look more like this
DECLARE likeRec_Count, likeRec_qId INT;
After reading your code, if you aren't adding to your cursor, you can simplify by using the following sql instead, which does the same thing as your cursor.
UPDATE qentry JOIN likecounttable l ON l.qId=qentry.qId
SET qentry.likeCount = l.likeCount
;
EDIT: If you wanted a complete update to your cursor, the following should do the same thing.
DELIMITER $$
CREATE PROCEDURE curLike()
BEGIN
DECLARE c_likeRec_isdone BOOLEAN DEFAULT FALSE;
DECLARE likeRec_Count, likeRec_qId INT;
DECLARE c_likeCount CURSOR FOR SELECT l.likeCount, l.qId FROM likecounttable l;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET c_likeRec_isdone = TRUE;
OPEN c_likeCount;
loop_likeRecList: LOOP
FETCH c_likeCount INTO likeRec_Count, likeRec_qId;
IF c_likeRec_isdone THEN
SET c_likeRec_isdone = FALSE;
LEAVE loop_likeRecList;
END IF;
UPDATE qentry SET qentry.likeCount = likeRec_Count WHERE qentry.qId=likeRec_qId;
END LOOP loop_likeRecList;
CLOSE c_likeCount;
END;
$$
CREATE PROCEDURE curLike()
BEGIN
DECLARE likeRec_Count, likeRec_qId INT;
DECLARE c_likeCount CURSOR FOR SELECT l.likeCount, l.qId FROM likecounttable l;
OPEN c_likeCount;
start_loop:LOOP
FETCH c_likeCount INTO likeRec_Count,likeRec_qId
UPDATE qentry SET qentry.likeCount = likeRec_Count WHERE qentry.qId=likeRec_qId ;
END LOOP;
CLOSE c_likeCount;
END;

MySQL Trigger with cursor returning error 1442 or not having an effect at all

I am currently using a database to handle an ingame inventory.
I have written a trigger in mySQL to try and have the items combine every time a new one is inserted in the table. Each item has two components.
I am doing something very wrong, but I can't see what it might be. This is my trigger:
CREATE TRIGGER `onitempickup` AFTER INSERT ON
`inventory` FOR EACH ROW BEGIN
BEGIN
DECLARE done boolean DEFAULT false;
DECLARE Item2Combine VARCHAR(10);
DECLARE MadefromResult1 VARCHAR(10);
DECLARE MadefromResult2 VARCHAR(10);
DECLARE ComboItemName1 VARCHAR(10);
DECLARE ComboItemName2 VARCHAR(10);
DECLARE in_itemname VARCHAR(10);
DECLARE Madefromcheck1Cursor cursor for
SELECT name, madefrom1 FROM item WHERE madefrom2 = in_itemname;
DECLARE Madefromcheck2Cursor cursor for
SELECT name, madefrom2 FROM i``tem WHERE madefrom1 = in_itemname;
DECLARE ItemToCombineCursor cursor for
SELECT Item from inventory;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET in_itemname = NEW.Item;
OPEN MadefromCheck1Cursor;
OPEN MadefromCheck2Cursor;
OPEN ItemToCombineCursor;
read_loop: LOOP
FETCH ItemToCombineCursor INTO Item2Combine;
FETCH Madefromcheck1Cursor INTO ComboItemName1, MadefromResult1;
FETCH MadefromCheck2Cursor INTO ComboItemName2, MadefromResult2;
IF done THEN
LEAVE read_loop;
ELSEIF Item2Combine = MadefromResult1 THEN
INSERT INTO Inventory(Item) VALUES(ComboItemName1);
DELETE FROM Inventory WHERE Item = in_itemname;
DELETE FROM Inventory WHERE Item = Item2Combine;
LEAVE read_loop;
ELSEIF Item2Combine = MadefromResult2 THEN INSERT
INTO Inventory(Item) VALUES(ComboItemName2);
DELETE FROM Inventory WHERE Item = in_itemname;
DELETE FROM Inventory WHERE Item = Item2Combine;
LEAVE read_loop;
ELSE
ITERATE read_loop;
END IF;
END LOOP read_loop;
CLOSE Madefromcheck1Cursor;
CLOSE Madefromcheck2Cursor;
CLOSE ItemToCombineCursor;
END
I have tried to change it to act before the insert to no avail, as the procedure did not even execute. I currently get an error 1442 implying that I have an infinite loop somewhere according to many questions here on stack overflow, but I don't see where.
I appreciate any help. Thanks for your attention.