Small Procedure with Cursor for autocreate rows in tables (MYSQL) - mysql

i created an event that execute one time per month. Three tables are important here, Cuota(fee), Alumno(studient) and CuotaxAlumno(fee per studient).
My objective is create a row in table Cuota(fee) one time per month and then with that fee create a payment row for every studient (in table CuotaxAlumno).
I having syntax error in te FETCH line, line 19, and i don't find the problem. i will appreciate the help.
IS WORKING NOW. CODE UPDATED 13-04-2017 Thanks!
DELIMITER $$
CREATE PROCEDURE crearCuotas()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE referenciaMonto INT;
DECLARE referenciaAlumno INT;
DECLARE referenciaCuota INT;
DECLARE fecha DATE;
DECLARE cursorAlumno CURSOR FOR SELECT idAlumno FROM alumno WHERE idEstado=1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET referenciaMonto = (SELECT idMontoCuota FROM montocuota ORDER BY idMontoCuota DESC LIMIT 1);
SET fecha = CURDATE();
INSERT INTO cuota (idMontoCuota, fecha) VALUES(referenciaMonto, fecha);
SET referenciaCuota = (SELECT idCuota FROM cuota ORDER BY idCuota DESC LIMIT 1);
OPEN cursorAlumno;
fetch_loop: LOOP
FETCH cursorAlumno INTO referenciaAlumno;
IF done THEN
LEAVE fetch_loop;
END IF;
INSERT INTO cuotaxalumno(idAlumno, idCuota, idEstado) VALUES(referenciaAlumno, referenciaCuota, 5);
END LOOP;
CLOSE cursorAlumno;
END;
DELIMITER ;

You need to add a loop label:
CREATE PROCEDURE crearCuotas()
BEGIN
/* yada */
OPEN cursorAlumno;
fetch_loop: LOOP
FETCH cursorAlumno INTO referenciaAlumno;
IF done THEN
LEAVE fetch_loop;
END IF;
INSERT INTO cuotaxalumno (idAlumno, idCuota, idEstado)
VALUES (referenciaAlumno, referenciaCuota, 5);
END LOOP;
CLOSE cursorAlumno;
END;
This is because while the label is not required for creating a loop, it is required for the leave statement.

Related

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

why does MySQL Trigger that uses cursor only fetch one value

I have created a Trigger after INSERT on the table AcademicYearTermLevel which uses a cursor value fetched from another query. I want to use each cursor value in a while loop and insert rows into table SubjectYearTermLevel.
DROP TRIGGER IF EXISTS after_academicyearterm_insert
DELIMITER $$
CREATE TRIGGER after_academicyearterm_insert
AFTER INSERT
ON AcademicYearTerm
FOR EACH ROW
BEGIN
DECLARE temp INT;
DECLARE subj_done, form_done BOOLEAN DEFAULT FALSE;
DECLARE s_id INT;
DECLARE curSubject CURSOR FOR SELECT subject_id FROM Subject;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET subj_done = TRUE;
SET temp = 1;
OPEN curSubject;
cur_subject_loop: LOOP
FETCH FROM curSubject INTO s_id;
IF subj_done THEN
CLOSE curSubject;
LEAVE cur_subject_loop;
END IF;
WHILE temp <= 6 DO
INSERT INTO SubjectYearTermLevel VALUES (NULL, s_id, NEW.yearTerm_id, temp);
SET temp = temp + 1;
END WHILE
END LOOP cur_subject_loop;
END$$
DELIMITER ;
However the problem is that the cursor only seems to fetch one value from the SELECT query
Silly mistake, I SET temp = 1; outside the FETCH, and hence after the first cursor value, the while loop never ran.
-- SET temp = 1;
OPEN curSubject;
cur_subject_loop: LOOP
FETCH FROM curSubject INTO s_id;
SET temp = 1;
IF subj_done THEN
CLOSE curSubject;
LEAVE cur_subject_loop;
END IF;
1_to_6_temp: WHILE temp <= 6 DO
INSERT INTO SubjectYearTermLevel VALUES (NULL, s_id, NEW.yearTerm_id, temp, -1);
SET temp = temp + 1;
END WHILE 1_to_6_temp;
-- CLOSE curSubject;
END LOOP cur_subject_loop;

MySQL puzzle: How to combine result in Loop?

So far I have tried using CREATE VIEW <view_table_name> and
CREATE TABLE <table_name> and CREATE TEMPORARY <temporary_table_name>
and this methods are taking so much time because I have to (step 1) create a table and (step 2) insert a data. Then (step 3) select the created table. Finally, (step 4) drop the table.
This is my procedure: (My program doesn't look make any sense, I mean why am I doing this. The answer to your confusion is, this is just a part of my large code and I made it this way so that it may look simple.)
BEGIN
-- Main loop variables
DECLARE col_Name varchar(255);
DECLARE col_Description varchar(255);
-- Main Loop
Block2: BEGIN
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE statement CURSOR FOR SELECT `name`, `description` FROM `rules`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN statement;
REPEAT
MainLoop: LOOP
FETCH statement INTO col_Name, col_Description;
IF done THEN
LEAVE MainLoop;
END IF;
SELECT col_Name AS `Name`, col_Description AS `Description`;
END LOOP MainLoop;
UNTIL done END REPEAT;
CLOSE statement;
END Block2;
-- End of Main Loop
END
The result is:
The problem:
The result is separate. How do I combine this result into one table?
Declare a temporary table at the beginning ,populate data into temp table and then access it after loop ends
BEGIN
-- Main loop variables
DECLARE col_Name varchar(255);
DECLARE col_Description varchar(255);
create temporary table yourtable (name varchar(50),description varchar(50));
-- Main Loop
Block2: BEGIN
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE statement CURSOR FOR SELECT `name`, `description` FROM `rules`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN statement;
REPEAT
MainLoop: LOOP
FETCH statement INTO col_Name, col_Description;
IF done THEN
LEAVE MainLoop;
END IF;
insert into yourtable(name,description)
values (col_Name, col_Description)
END LOOP MainLoop;
UNTIL done END REPEAT;
CLOSE statement;
select * from yourtable
END Block2;
-- End of Main Loop
END
I think things can be easier.
you don't have to use a cursor, you just need to create an empty table in your procedure, and input the result from your query.
like below:
CREATE DEFINER=`root`#`localhost` PROCEDURE `temp`(val int)
BEGIN
DECLARE yourval datatype()
-- declare as many as you need.---
set #beginning = 0
set #ending = val
-- how many time do you need to repeat your code?
---CREATE AN EMPTY TABLE HERE---
while #beginning < #ending do
insert table TableCreatedAbove
---YOUR QUERY---
---YOU MAY NEED TO DO SOMETHING WITH YOUR DECLARED VARIABLE---
set #beginning = #beginning + 1;
end while;
commit;
END
when you need to use your combined table, just
select * from TableCreatedAbove
maybe you already solved your problem in somewhere else, but here is my answer.

Get Columns Single Record in Stored Procedure Mysql

I have my procedure and is working, but my question is the following,
with the cursor is working correctly, but before the cursor I need a Single Record with several columns, I donĀ“t know if I need another cursor just for one record.
Which would be the right way to get the columns of that single row without a cursor.
The query to execute is:
'SELECT id,anio,fec_iniciointeres FROM mytable WHERE id=3 '
DELIMITER $$
DROP PROCEDURE IF EXISTS db.cal_intereses$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `cal_intereses`()
BEGIN
DECLARE factura_id INT UNSIGNED;
DECLARE val_avaluo DECIMAL(16,2);
DECLARE fec_actual DATE;
DECLARE done INT;
DECLARE cur CURSOR FOR SELECT fac_facturas.id AS factura_id, fac_facturas.val_avaluo FROM fac_facturas WHERE fac_facturas.vigencia_id<=26 AND fac_facturas.estado=1 AND fac_facturas.val_avaluo>0 LIMIT 10;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
SET fec_actual=(SELECT CURDATE());
SET done = 0;
OPEN cur;
ciclo: LOOP
FETCH cur INTO factura_id,val_avaluo;
IF done=1 THEN LEAVE ciclo; END IF;
DELETE FROM val_interesaux;
IF fec_actual>='2006-07-29' THEN
INSERT INTO val_interesaux(factura_id,fec_inicio) VALUES(factura_id,fec_actual);
END IF;
END LOOP ciclo;
CLOSE cur;
END$$
DELIMITER ;

How to exexute mysql event at a perticular time with out using if

Iam Using following code to run this event using
IF CURRENT_TIME() = '23:50:00'
But doing so, every second it has to compare the time with server time. can we implement this with out if condistion
drop event OEAuditEvent;
DELIMITER $$
CREATE EVENT OEAuditEvent
ON SCHEDULE EVERY 1 SECOND
STARTS '2012-08-30 09:00:10'
DO
BEGIN
DECLARE a CHAR(20);
DECLARE b,c,d INT;
DECLARE done INT DEFAULT FALSE;
IF CURRENT_TIME() = '23:50:00' THEN
begin
DECLARE cur CURSOR FOR select OE_User,count(OE_User) from RNCM_Status where date(OE_Date)=CURDATE() group by OE_User;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO a, b;
SET c=ceil((b*5)/100);
insert into test values(a,b);
IF done THEN
LEAVE read_loop;
ELSE
insert into OE_Audit(MDN,CAF,UploadedDate,OEUser,OEDate,UserCount,QCCount,intime) select MDN,CAF,UploadedDate,OE_User,OE_Date,b,c,now() from RNCM_Status where OE_User=a and date(OE_Date)=CURDATE() order by rand() limit c;
END IF;
END LOOP;
CLOSE cur;
end ;
END IF;
END $$
DELIMITER ;
Why exactly not create the event itself to run daily at 23:00 and remove IF completely?
CREATE EVENT OEAuditEvent
ON SCHEDULE EVERY 1 DAY
STARTS '2012-08-30 23:00:00'