MySQL Stored Procedure not functioning properly Nested cursors - mysql

Please note the first cursor fetches 3 results and when I insert it inserts only 1. Earlier when I did not have open curs2, it was functioning fine, but now it doesn't. I might have missed some with done and done2 variables as I am writing a stored procedure after a long time. Please see if you may find anything wrong.
Thanks
BLOCK1: begin
declare done INT DEFAULT FALSE;
declare gid BIGINT;
declare activity_name VARCHAR(255) ;
declare type_1 VARCHAR(255) ;
declare shop_activity_id BIGINT;
declare curs CURSOR for select id, activityName, `Type`, shopActivityId from gantttask where `Type` = 'Project';
open curs;
LOOP1: loop
fetch curs into gid, activity_name, type_1, shop_activity_id;
if done then
leave LOOP1;
end if;
insert into gantttask_result VALUES (gid, activity_name, type_1, shop_activity_id);
BLOCK2: begin
declare done2 INT DEFAULT FALSE;
declare gid2 BIGINT;
declare activity_name2 VARCHAR(255) ;
declare type_2 VARCHAR(255) ;
declare shop_activity_id2 BIGINT;
declare curs2 CURSOR for select id, activityName, `Type`, shopActivityId from gantttask where `Type` != 'Project' and shopActivityId = shop_activity_id order by id;
open curs2;
LOOP2: loop
fetch curs2 into gid2, activity_name2, type_2, shop_activity_id2;
if done2 then
leave LOOP2;
end if;
end loop LOOP2;
close curs2;
end BLOCK2;
end loop LOOP1;
close curs;
end BLOCK1

Related

variable usage in nested cursors

I have a stored procedure snippet like this
CREATE DEFINER=`root`#`%` PROCEDURE `new_procedure`()
BEGIN
DECLARE c_id varchar(100) DEFAULT "";
DECLARE cursor1 CURSOR for select id from t1 where name like 's%';
OPEN cursor1;
get_t1: LOOP
FETCH cursor1 into c_id;
p:begin
declare cursor2 cursor for select id from t2 where cl_id=c_id;
open cursor2;
get_t2: loop
fetch project_cursor into p_id;
// perform some tasks
t:begin
declare cursor3 cursor for select id from t3 where pr_id=p_id;
open cursor3;
get_t3:loop
fetch cursor3 into t_id;
IF v_finished = 1 THEN
LEAVE get_t3;
END IF;
//perform some tasks
close cursor3;
select p_id;
end t;
end loop t2;
end p;
END LOOP t1;
END
here select statement is not displaying any data
when i write select under cursor 3 it is working.
did i made any mistake? anything I missed
Some basic logic has been added in your SP, Try it whether this is what you are expecting.
CREATE DEFINER=`root`#`%` PROCEDURE `new_procedure`()
BEGIN
DECLARE c_id VARCHAR(100) DEFAULT "";
DECLARE done1 BOOLEAN DEFAULT FALSE;
DECLARE cursor1 CURSOR FOR SELECT id FROM t1 WHERE name LIKE 's%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1=TRUE;
OPEN cursor1;
GET_T1: LOOP
FETCH cursor1 INTO c_id;
IF done1 THEN
LEAVE GET_T1;
END IF;
P:BEGIN
DECLARE p_id INT ; -- check which data types suits you, might be int
DECLARE done2 BOOLEAN DEFAULT FALSE;
DECLARE cursor2 CURSOR FOR SELECT id FROM t2 WHERE cl_id=c_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2=TRUE;
OPEN cursor2;
GET_T2: LOOP
FETCH cursor2 INTO p_id;
IF done2 THEN
LEAVE GET_T2;
END IF;
/* perform some task */
T:BEGIN
DECLARE t_id INT ; -- check which data types suits you, might be int
DECLARE done3 BOOLEAN DEFAULT FALSE;
DECLARE cursor3 CURSOR FOR SELECT id FROM t3 WHERE pr_id=p_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done3=TRUE;
OPEN cursor3;
GET_T3:LOOP
FETCH cursor3 INTO t_id;
IF done3 THEN
LEAVE GET_T3;
END IF;
/* perform some tasks */
#select p_id; -- don't know what you are doing with this
END LOOP GET_T3;
CLOSE cursor3;
SET done3=FALSE;
END T;
END LOOP GET_T2;
CLOSE cursor2;
SET done2= FALSE;
END P;
END LOOP GET_T1;
CLOSE cursor1;
SET done1= FALSE;
END

Mysql Store procedure stops iteration after some rows

Below procedure code running with out error . Line select FOUND_ROWS() returning n no. rows but cursor curs did not loop all rows
CREATE DEFINER=`root`#`%` PROCEDURE `middleLocationAutoUpdatePorc`()
BEGIN
declare vname varchar(45);
declare vmobile varchar(20);
declare vsapid varchar(6);
declare vuser varchar(45);
declare vday date;
declare vmintime time;
declare vmaxtime time;
declare vminLocation mediumtext;
declare vmaxLocation mediumtext;
declare vmiddlelocation mediumtext;
declare vdistance int(11);
declare vdrdid int(11);
declare vn_no_details int(11);
declare uatt varchar(45) default 'X';
declare adatta varchar(45) default 'X';
declare b_not_found BOOL DEFAULT FALSE;
declare curs CURSOR FOR
SELECT user ,day, mintime,maxtime_mobile,minLocation,maxLocation,distance,n_no_details,drdid FROM mydb.statusreport where day >= '2017-06-26';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET b_not_found = true;
OPEN curs;
loop1: LOOP
FETCH curs INTO vuser,vday,vmintime,vmaxtime,vminLocation,vmaxLocation,vdistance,vn_no_details,vdrdid;
IF b_not_found THEN
LEAVE loop1;
END IF;
-- select FOUND_ROWS();
case substring_index(vuser,"-",-1)
when 'RSM' then
select username,Name,mobile into vsapid,vname,vmobile from mydb.supervisor where idSu=CONVERT(substring_index(vuser,"-",1),UNSIGNED INTEGER);
when 'ASM' then
select userName,name,mobile into vsapid,vname,vmobile from mydb.executive where exeid=CONVERT(substring_index(vuser,"-",1),UNSIGNED INTEGER);
when 'F' then
select sapId,name,phone into vsapid,vname,vmobile from mydb.user where idUser=CONVERT(substring_index(vuser,"-",1),UNSIGNED INTEGER);
end case;
select userGiven , adminGiven into uatt ,adatta from userdaystatus st where st.date =vday and st.idUser=CONVERT(substring_index(vuser,"-",1),UNSIGNED INTEGER) and st.userType=substring_index(vuser,"-",-1);
set vmiddlelocation=( select location from mydb.dailyReportDetails as dtb where dtb.idDailyReport=vdrdid and dtb.counter>=(abs(vn_no_details/2) ) order by dtb.idDailyReportDetails asc limit 1);
call mydb.addOMiddleLocation(day(vday), month(vday),
year(vday),vuser, vname,
vsapid, vmobile, vmintime,
vmaxtime, SUBTIME(vmaxtime,vmintime),
vminLocation,
vmiddlelocation,
vmaxLocation,Round(vdistance/1000,2),
uatt, adatta);
END LOOP;
CLOSE curs;
END
The Procedure call mydb.addOMiddleLocation() just inserting Row on another table.There does not have any data type validation .
So what can be the problem ?
It happen for log wait time for a particular Query line
set vmiddlelocation=( select location from mydb.dailyReportDetails as dtb where dtb.idDailyReport=vdrdid and dtb.counter>=(abs(vn_no_details/2) ) order by dtb.idDailyReportDetails asc limit 1);

How to add two cursor values and UPDATE the table

I want to add two cursor values where vehicle_id and vehicleno should be the same and then update the table.
example:
1.value from cur2 , totkm_t
2.value from cur3 , totkm_l
I want to add these two i.e.
totkm_f = totkm_t + ktotm_l
and then
update fuelavg SET totkm=totkm_f where vid=vid_l;
I also want such addition for other store pump but my stored procedure returns null values.
DELIMITER $$
DROP PROCEDURE IF EXISTS `searchvehicle`.`fuelavg`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `fuelavg`(IN startdate DATE, IN enddate DATE)
BEGIN
DECLARE vname_c VARCHAR(40);
DECLARE vnostring_c varchar(30);
DECLARE vowner_c varchar(40);
DECLARE vid_c,vmax_c,vmin_c,vcmpny_c,vtype_c INT;
DECLARE done INT DEFAULT FALSE;
DROP TABLE IF EXISTS fuelavg;
CREATE TABLE fuelavg
(
id int not null auto_increment primary key,
vid int,
vname varchar(40),
vnostring varchar(30),
v_type int,
vowner varchar(40),
store int,
pump int,
other int,
totfuel int,
totkm int,
vehavrg float,
cmpnyavg int,
maxavg int,
minavg int
);
BLOCK1: BEGIN
DECLARE CUR1 CURSOR FOR SELECT vehicle_owner.vid,vehicle_owner.vname, vehicle_owner.vowner,vehicle_owner.vnostring,vehicle_owner.vtype,vehicle_owner.vcompnyavg,vehicle_owner.maxavg,vehicle_owner.minavg FROM vehicle_owner;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
OPEN CUR1;
READ_LOOP: LOOP
FETCH CUR1 INTO vid_c,vname_c,vowner_c,vnostring_c,vtype_c,vcmpny_c,vmax_c,vmin_c;
IF done THEN LEAVE READ_LOOP;
END IF;
SET autocommit=0;
INSERT INTO fuelavg(vid,vname,vnostring,vowner,v_type,cmpnyavg, maxavg,minavg)values(vid_c,vname_c,vnostring_c,vowner_c,vtype_c,vcmpny_c,vmax_c,vmin_c);
END LOOP;
CLOSE CUR1;
END BLOCK1;
BLOCK2: BEGIN
DECLARE vid_t,totkm_t,store_t,pump_t,other_t INT;
DECLARE vnostring_t VARCHAR(30);
DECLARE indate_t,outdate_t DATE DEFAULT FALSE;
DECLARE vid_l,totkm_l,store_l,pump_l,other_l INT;
DECLARE vnostring_l VARCHAR(30); `enter code here`
DECLARE vid_f,totkm_f,store_f,pump_f,other_f INT;
DECLARE vnostring_f VARCHAR(30);
DECLARE done INT DEFAULT FALSE;
DECLARE CUR2 CURSOR FOR SELECT logentry.vid,logentry.vnostring,sum(logentry.totkm),sum(logentry.other),sum(logentry.store),sum(logentry.pump) FROM logentry WHERE indate>=startdate and indate<=enddate group by vid,vnostring;
DECLARE CUR3 CURSOR FOR SELECT logentry.vid,logentry.vnostring,sum(logentry.totkm),sum(logentry.store),sum(logentry.other),sum(logentry.pump) FROM LOGENTRY WHERE INDATE<=(SELECT MAX(INDATE) FROM LOGENTRY WHERE TANKFULL=1 AND INDATE<startdate)AND tankfull=1 GROUP BY VID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
OPEN CUR2;
OPEN CUR3;
READ_LOOP: LOOP
FETCH CUR2 INTO vid_t,vnostring_t,totkm_t,other_t,store_t,pump_t;
IF done THEN LEAVE READ_LOOP;
END IF;
FETCH CUR3 INTO vid_l,vnostring_l,totkm_l,other_l,store_l,pump_l;
IF done THEN LEAVE READ_LOOP;
END IF;
UPDATE fuelavg SET totkm=(totkm_t+totkm_l),other=(other_t+other_l),store=(store_t+store_l),pump=(pump_t+pump_l) WHERE vid=vid_t AND vnostring=vnostring_t;
IF done THEN LEAVE READ_LOOP;
END IF;
SET autocommit=1;
END LOOP;
CLOSE CUR2;
CLOSE CUR3;
END BLOCK2;
select * from fuelavg;
output file attached here which currently the above query that show null values.
Finally my efforts was fruitful. The following is the code where I updated the table by adding two cursor values.
DELIMITER $$
DROP PROCEDURE IF EXISTS `searchvehicle`.`fuelavg2`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `fuelavg2`(IN startdate DATE, IN enddate DATE)
BEGIN
DECLARE vname_c VARCHAR(40);
DECLARE vnostring_c varchar(30);
DECLARE vowner_c varchar(40);
DECLARE vid_c,vmax_c,vmin_c,vcmpny_c,vtype_c INT;
DECLARE done INT DEFAULT FALSE;
DROP TABLE IF EXISTS fuelavg;
CREATE TABLE fuelavg
(
id int not null auto_increment primary key,
vid int,
vname varchar(40),
vnostring varchar(30),
v_type int,
vowner varchar(40),
store int,
pump int,
other int,
totfuel int,
totkm int,
vehavrg int,
cmpnyavg int,
maxavg int,
minavg int
);
BLOCK1: BEGIN
DECLARE CUR1 CURSOR FOR SELECT vehicle_owner.vid,vehicle_owner.vname,vehicle_owner.vowner,vehicle_owner.vnostring,vehicle_owner.vtype,vehicle_owner.vcompnyavg,vehicle_owner.maxavg,vehicle_owner.minavg FROM vehicle_owner;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
OPEN CUR1;
READ_LOOP: LOOP
FETCH CUR1 INTO vid_c,vname_c,vowner_c,vnostring_c,vtype_c,vcmpny_c,vmax_c,vmin_c;
IF done THEN LEAVE READ_LOOP;
END IF;
SET autocommit=0;
INSERT INTO fuelavg(vid,vname,vnostring,vowner,v_type,cmpnyavg, maxavg,minavg)values(vid_c,vname_c,vnostring_c,vowner_c,vtype_c,vcmpny_c,vmax_c,vmin_c);
END LOOP;
CLOSE CUR1;
END BLOCK1;
BLOCK2: BEGIN
DECLARE vid_t,totkm_t,store_t,pump_t,other_t INT;
DECLARE vnostring_t VARCHAR(30);
DECLARE indate_t,outdate_t DATE DEFAULT FALSE;
DECLARE vid_l,totkm_l,store_l,pump_l,other_l INT;
DECLARE vnostring_l VARCHAR(30);
DECLARE vid_f,totkm_f,store_f,pump_f,other_f INT;
DECLARE vnostring_f VARCHAR(30);
DECLARE vid_a,totfuel_a INT;
DECLARE vehavrg_a INT;
DECLARE vnostring_a VARCHAR(30);
DECLARE done,done3,done2,done5 INT DEFAULT FALSE;
DECLARE CUR2 CURSOR FOR SELECT logentry.vid,logentry.vnostring,sum(logentry.totkm),sum(logentry.other),sum(logentry.store),sum(logentry.pump) FROM logentry WHERE indate>=startdate and indate<=enddate group by vid,vnostring;
DECLARE CUR4 CURSOR FOR SELECT logentry.vid,logentry.vnostring,sum(logentry.totkm),sum(logentry.other),sum(logentry.store),sum(logentry.pump) FROM logentry WHERE indate>=startdate and indate<=enddate group by vid,vnostring;
DECLARE CUR3 CURSOR FOR SELECT logentry.vid,logentry.vnostring,sum(logentry.totkm),sum(logentry.store),sum(logentry.other),sum(logentry.pump) FROM LOGENTRY WHERE INDATE<=(SELECT MAX(INDATE) FROM LOGENTRY WHERE TANKFULL=1 AND INDATE<startdate)AND tankfull=1 GROUP BY VID;
OPEN CUR2;
BLOCK5:BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
OPEN CUR4;
/* update table by value of traversing the tankfull of last month */
READ_LOOP5:LOOP
FETCH CUR4 INTO vid_t,vnostring_t,totkm_t,other_t,store_t,pump_t;
IF done THEN LEAVE READ_LOOP5;
END IF;
UPDATE fuelavg SET totkm=totkm_t,other=other_t,store=store_t,pump=pump_t WHERE vid=vid_t;
IF done THEN LEAVE READ_LOOP5;
END IF;
END LOOP READ_LOOP5;
END BLOCK5;
BLOCK3:BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done3=TRUE;
OPEN CUR3;
READ_LOOP3:LOOP
FETCH CUR3 INTO vid_l,vnostring_l,totkm_l,other_l,store_l,pump_l;
IF done3 THEN LEAVE READ_LOOP3;
END IF;
/**********************/
/* update table by value of traversing the tankfull of last month */
BLOCK4:BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2=TRUE;
READ_LOOP2:LOOP
FETCH CUR2 INTO vid_t,vnostring_t,totkm_t,other_t,store_t,pump_t;
IF done3 THEN LEAVE READ_LOOP2;
END IF;
UPDATE fuelavg SET totkm=totkm_t+totkm_l,other=other_t+other_l,store=store_t+store_l,pump=pump_t+pump_l WHERE vid=vid_t AND vid=vid_l ;
IF done2 THEN LEAVE READ_LOOP2;
END IF;
END LOOP READ_LOOP2;
END BLOCK4;
/**********************/
END LOOP READ_LOOP3;
END BLOCK3;
/* calculate totfuel,averge*/
BLOCK5:BEGIN
DECLARE CUR5 CURSOR FOR SELECT fuelavg.vid,fuelavg.vnostring,(SUM(fuelavg.other) + SUM(fuelavg.pump) + SUM(fuelavg.store)) AS 'tot_fuel',(SUM(fuelavg.totKM)/ (SUM(fuelavg.other)+SUM(fuelavg.pump)+SUM(fuelavg.store))) AS 'veh_avrg' FROM fuelavg group by vid,vnostring;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done5=TRUE;
OPEN CUR5;
READ_LOOP6:LOOP
FETCH CUR5 INTO vid_a,vnostring_a,totfuel_a,vehavrg_a;
IF done5 THEN LEAVE READ_LOOP6;
END IF;
UPDATE fuelavg SET totfuel=totfuel_a,vehavrg=vehavrg_a WHERE vid=vid_a AND vnostring=vnostring_a;
IF done5 THEN LEAVE READ_LOOP6;
END IF;
END LOOP READ_LOOP6;
CLOSE CUR5;
END BLOCK5;
/**********************/
CLOSE CUR3;
CLOSE CUR2;
CLOSE CUR4;
END BLOCK2;
select * from fuelavg;
END$$
DELIMITER ;`

Need help customizing mysql trigger

This is my current trigger:
DELIMITER $$
CREATE DEFINER=`root`#`127.0.0.1` TRIGGER `unique_visit_new_campaign` AFTER INSERT ON `unique_visit` FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pixel_id int;
DECLARE campaign_id varchar(45);
DECLARE cur CURSOR FOR SELECT id FROM pixels;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO pixel_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT IGNORE INTO pixels_campaign (campaign_id , pixel_id , date) VALUES (NEW.campaign_id ,pixel_id, current_timestamp);
END LOOP;
CLOSE cur;
END
I need it to NOT TRIGGER when new.campaign_id is empty or equals to the string {campaign_id}
I tried using MySQL IF but with no success.
Also, It kinda auto increment even when there is a campaign id already (when it ignores). any way I can stop that from happening?
Did you try this?
DELIMITER $$
CREATE DEFINER=`root`#`127.0.0.1` TRIGGER `unique_visit_new_campaign` AFTER INSERT ON `unique_visit` FOR EACH ROW
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE pixel_id int;
DECLARE campaign_id varchar(45);
DECLARE cur CURSOR FOR SELECT id FROM pixels;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
IF new.campaign = '' or new.campaign = '{campaign_id}' or new.campaign is null THEN
OPEN cur;
ins_loop: LOOP
FETCH cur INTO pixel_id;
IF done THEN
LEAVE ins_loop;
END IF;
INSERT IGNORE INTO pixels_campaign (campaign_id , pixel_id , date) VALUES (NEW.campaign_id ,pixel_id, current_timestamp);
END LOOP;
CLOSE cur;
END IF
END

Using for loop in MySql data set

How to use for loop in MySQL data set ?
FOR x IN (SELECT column FROM table_name WHERE column_2 = input_val)
LOOP
sum_total := sum_total + x.column ;
END LOOP;
This is an example how I used to loop data set in oracle.
How can this be achieved in MySql ?
How about not looping at all. It's SQL after all.
SELECT SUM(`column`) total
FROM table_name
WHERE column_2 = <input_val>
Otherwise use CURSOR
Now, equivalent loop using CURSOR will look like
DELIMITER $$
CREATE PROCEDURE sp_loop(IN input_val INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE sum_current, sum_total INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT column1 FROM table_name WHERE column2 = input_val;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO sum_current;
IF done THEN
LEAVE read_loop;
END IF;
SET sum_total = sum_total + sum_current;
END LOOP;
CLOSE cur1;
SELECT sum_total;
END$$
DELIMITER ;
Here is SQLFiddle
DROP PROCEDURE IF EXISTS `foo`.`usp_cursor_example`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `foo`.`usp_cursor_example`(
IN name_in VARCHAR(255)
)
READS SQL DATA
BEGIN
DECLARE name_val VARCHAR(255);
DECLARE status_update_val VARCHAR(255);
-- Declare variables used just for cursor and loop control
DECLARE no_more_rows BOOLEAN;
DECLARE loop_cntr INT DEFAULT 0;
DECLARE num_rows INT DEFAULT 0;
-- Declare the cursor
DECLARE friends_cur CURSOR FOR
SELECT
name
, status_update
FROM foo.friend_status
WHERE name = name_in;
-- Declare 'handlers' for exceptions
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET no_more_rows = TRUE;
OPEN friends_cur;
select FOUND_ROWS() into num_rows;
the_loop: LOOP
FETCH friends_cur
INTO name_val
, status_update_val;
IF no_more_rows THEN
CLOSE friends_cur;
LEAVE the_loop;
END IF;
select name_val, status_update_val;
-- count the number of times looped
SET loop_cntr = loop_cntr + 1;
END LOOP the_loop;
-- 'print' the output so we can see they are the same
select num_rows, loop_cntr;
END
DELIMITER ;