Why MySQL Cursor stopped looping while reporting a success - mysql

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

Related

How should I calculate sum of all values in a field using cursor in mysql?

Select sum(balance) as total_asset from account_details;
I should replace this query using cursor of stored procedure in MySQL
CREATE PROCEDURE `GetTotalBankAsset`()
BEGIN
DECLARE c_balance INT DEFAULT 0;
DECLARE sum INT DEFAULT 0;
DECLARE sumCurs CURSOR FOR Select balance from account_details;
OPEN sumCurs;
getSum: LOOP
FETCH NEXT FROM sumCurs INTO c_balance;
SET sum=c_balance+sum;
LEAVE getSum;
END LOOP;
SELECT sum;
CLOSE sumCurs;
END
This is the procedure I wrote. But here I only get value from single
row. How can I process multiple rows?
You can use a handler to leave the loop like this:
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE c_balance INT DEFAULT 0;
DECLARE sum INT DEFAULT 0;
DECLARE sumCurs CURSOR FOR Select balance from account_details;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN sumCurs;
getSum: LOOP
FETCH NEXT FROM sumCurs INTO c_balance;
IF done THEN
LEAVE getSum;
END IF;
SET sum=c_balance+sum;
END LOOP;
CLOSE sumCurs;
SELECT sum(sum);
END

cursor within a trigger

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

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;

Nested Cursors in MySQL Procedures

I need to iterate through a particular table for some conditions.On that conditions it will return a list of row data,which i need to delete in the procedure,but the data is linked with multiple other tables so what I thought to do is to get the primary key of the fetched rows in one cursor and concatenate it with comma in my first iteration and with that concatenated list I can do one query to fetch datas from linked tables (using FIND_IN_SET function)...
I tried something like this which is not working as expected...Can anyone please tell me whether this can be possible to do or to do in anyother way...
Here in this example,
There are two tables scmn_sop_dtls and scmn_sop_addnl_dtls,these two tables have foreign key relation with one column so,what i'm trying to do is i'll fetch some details from scmn_sop_dtls and insert into record table and the one i'm inserting i need to delete in scmn_sop_dtls table.So when i delete it is throwing foreign key relation error since it is linked with scmn_sop_addnl_dtls.So first i need to collect all the sopid and concatenated into list and that list i'm passing to the second cursor to fetch that particular row from child table(scmn_sop_addnl_dtls). but it is not fetching them.
DELIMITER $$
USE `scmn_nov21`$$
DROP PROCEDURE IF EXISTS `MoveSampleData`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `MoveSampleData`()
BEGIN
Block1: BEGIN
DECLARE done INT DEFAULT 0;
DECLARE par_sop_id VARCHAR(50);
DECLARE par_sop_addnl_id VARCHAR(50);
DECLARE sopdl_sop_id_list VARCHAR(500);
DECLARE sopdl_sop_param_list VARCHAR(500);
DECLARE sopdl_temp_sop_param_list VARCHAR(500);
DECLARE sopdl_temp_sop_id VARCHAR(10);
DECLARE c_1 CURSOR FOR SELECT sop_id FROM scmn_sop_dtls WHERE created_date < NOW() - INTERVAL 1 MONTH;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN c_1;
REPEAT
FETCH c_1 INTO par_sop_id;
INSERT INTO record VALUES(par_sop_id,"Sub","Sop data","NIL",0,NOW());
SET sopdl_temp_sop_id = CONCAT(par_sop_id, ',');
SET sopdl_sop_id_list = CONCAT(sopdl_sop_id_list, sopdl_temp_sop_id);
Block2: BEGIN
DECLARE done2 INT DEFAULT 0;
DECLARE c_2 CURSOR FOR SELECT sop_addnl_id FROM scmn_sop_addnl_dtls WHERE FIND_IN_SET(sop_id,sopdl_sop_id_list);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = 1;
OPEN c_2;
REPEAT
FETCH c_2 INTO par_sop_addnl_id;
INSERT INTO record_arc VALUES(par_sop_addnl_id,"Sub","Sop data","NIL",0,NOW());
UNTIL done2 END REPEAT;
CLOSE c_2;
END Block2;
UNTIL done END REPEAT;
CLOSE c_1;
END Block1;
END$$
DELIMITER ;

MySQL procedure loop stops after one iteration

I am working on a MySQL procedure that creates a summary of one of my tables. The procedure retrieves a dataset and loops through it using a cursor. For each iteration of the loop, the procedure updates another table. The problem I'm having is the loop ends after a single iteration, event though I know that the query I'm running retrieves more than one row.
BEGIN
# Variable declaration section omitted for brevity
DECLARE cur CURSOR FOR SELECT
t.result_id,
t.athlete_id, t.`first`, t.middle, `last`, t.pref, t.birth,t.uss,
t.club_id,t.code,t.club_name,
t.meet_name,t.meet_id,t.`start`,t.`end`,
MIN(t.time) as time,t.age,t.type
FROM sometable t GROUP BY club_id ORDER BY time asc,t.start desc,club_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO result_id,athlete_id, first_name, middle, last_name, pref, birth,uss,
club_id,club_code,club_name,
meet_name,meet_id,start_date,end_date,
result_time,age,type;
IF done=1 THEN
LEAVE read_loop;
END IF;
SET last_time = result_time;
INSERT INTO toptimes(`result_id`,`club_id`,`agegroup`,`sex`,`distance`,`course`,`stroke`,`data`,`published`)
VALUES(result_id,club_id,AgeGroupID,sex,distance,course,stroke,json,0);
END LOOP read_loop;
CLOSE cur;
END
I'm not clear what the problem is. When I run the select query manually, I get back several rows. Is there a problem running an insert statement inside the loop?
Your code chunk looks good to me.
How do you know that it's running only one iteration (i'm not seeing any
print or select statement for debug purpose)?
Are you getting any error while executing the stored procedure?
I tried to replicate the similar code with "sakila" database (mysql sample db). It's working perfectly. Please check this sql code sample, if it helps you.
DROP PROCEDURE IF EXISTS usp_select_dummy_data ;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE usp_select_dummy_data()
BEGIN
-- Declare your variables
Declare _var_actor_id int default 0;
DECLARE _var_film_id int default 0;
-- Declare variable used for cursor and loop control
DECLARE done int;
DECLARE loop_counter INT DEFAULT 0;
-- Declare the cursor
DECLARE cur CURSOR FOR
SELECT
actor_id, film_id
FROM film_actor;
-- Declare handlers
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Open the cursor
OPEN cur ;
-- Start the loop
read_loop: LOOP
FETCH cur
INTO _var_actor_id, _var_film_id ;
-- break out of the loop if
-- 1. if there is no rows or
-- 2. we've processed them all
IF done = 1 THEN
CLOSE cur ;
LEAVE read_loop ;
END IF;
-- Count the number of times looped
SET loop_counter = loop_counter + 1 ;
END LOOP read_loop ;
-- print the loop count
select loop_counter;
END