MySql Procedure GOTO Statement - mysql

I want to use goto statement in Mysql stored procedure in such manner that I execute my cursor whenever condition become true once again.
This is a sample code only, I just looking for goto statement
BLOCK_BACKLOG:begin
declare backlgId, oldCOR, oldATR,oldCourse,oldATR,isFormFilled,nextParentId int;
declare backlogNoMoreRow boolean default false;
Label : TestLineStart
declare backlogCur cursor for select bcklg.id,cor.id,atr.id,cr.id,atr.obtainedMarks,atr.isFormFilled,atr.parentRegistration_id
from train bcklg,bus cor,fliet atr,fair co,distance cr
where bcklg.courseofferingregistration_id=cor.id and cor.academictermregistration_id=atr.id and cor.courseoffering_id=co.id and co.course_id=cr.id
and bcklg.isDeleted is false and atr.id=parentId;
declare continue handler for not found set backlogNoMoreRow=true;
open backlogCur;
LOOP_BACKLOG: loop
fetch backlogCur into backlgId, oldCOR, oldATR,oldCourse,oldATRMarks,isFormFilled,nextParentId;
if backlogNoMoreRow then
close backlogCur;
leave LOOP_BACKLOG;
end if;
if isFormFilled==0 then
parentId=nextParentId;
GOTO TestLineStart;
end if;

You can use a LOOP on the outer block based on the value for variable isFormFilled.
Following change may help you.
-- Label : TestLineStart
TestLineStart: LOOP
-- other part of your SP as it is
and make following change:
if isFormFilled==0 then
parentId=nextParentId;
-- GOTO TestLineStart;
else
leave TestLineStart;
end if;
You have to close all loop statements properly.

Related

basic cursor mysql with loop

I've been trying to create a cursor but for some reason i keep getting an error saying theres something wrong with the syntax.
what im asking is for a basic cursor that i can use with a loop so that i can call a function for each row. literally a mysql equivelent of php foreach loop
function functionName ($commentId){
$i = 0;
foreach (commentId as value) {
//inside here we would do whatever function we would like but for this example i just want a basic increment to keep things simple and easy to understand
$i++;
}
echo $i;}
functionName(76);
i understand php is a little bit different as i would first need to select the rows using a mysql query and have the $commentId variable equal to the but i was just using this as an example to make this question as clear as i can make it.
here is my example that keeps failing
DELIMITER $$
create function functionName(commentOn int(11)) returns int
BEGIN
DECLARE done INT DEFAULT FALSE;
declare var int;
declare anotherVar int;
set var = 0;
set anotherVar = 0;
DECLARE cur1 CURSOR FOR SELECT id FROM comments where `commentOnComment` = commentOn;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO anotherVar;
set var = var + 1;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE cur1;
return var;
END; $$
DELIMITER ;
select functionName(76);
to explain what this example is in a little more detail, there is a table full of comments, the comment id and the id of the comment the user commented on (commentOnComment). and in the end i want to loop through all of the comments and select all where the commentOnComment equals the id of the comment the user commented on so that i can see how much replies each comment has i will change the increment to a select count(*) from comments where commentOnComment = commentOn; the commentOn parameter will be the id of the comment. But for the answer shown for this question i just want an increment to keep it simple and easy for myself and other people to understand.
Thanks to P.Salmon i was able to get a basic cursor with loop working, it was just the order of my code that was the problem. Im very greatfull as a little mistake like this would have taken me forever to figure out especially with the fact that i had never done a working cursor before.
here is the code for a basic cursor that does a function for each row in a table, in this example it increments the value of a variable by 1.
DELIMITER $$
create function functionName(commentOn int(11)) returns int
BEGIN
DECLARE done INT DEFAULT FALSE;
declare var int;
declare anotherVar int;
DECLARE cur1 CURSOR FOR SELECT id FROM comments where `commentOnComment` = commentOn;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
set var = 0;
set anotherVar = 0;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO anotherVar;
IF done THEN
LEAVE read_loop;
END IF;
/*comment here is the area where you can add whatever insert, update, select or any
type of function you would like for each row. This is literally mysql's version of
php's foreach loop*/
set var = var + 1;
END LOOP;
CLOSE cur1;
return var;
END; $$
DELIMITER ;
as you can see its very similar to the question i just needed to change the order of my code. a simple select functionName(id); will give you the output, the id can be any number, in this example it would be the id of the row.
I am also curious as to why many people viewed this question but didnt answer, consequentially causing me to have to answer myself? if P.Salmon didnt comment and tell me the problem i would still be stuck. i tried to be as clear as i could, was it difficult to understand? was the question too hard for most people? feedback would be highly appreciated as it will help me in my future questions.

Warning 1329 no data fetched

delimiter ;;
create procedure cd3(out var int)
begin
declare finished int default 0;
declare cur cursor for select id from a;
declare continue handler for not found set finished=1;
open cur;
curloop:loop
fetch cur into var;
if finished then
leave curloop;
end if;
end loop curloop;
close cur;
end;;
call cd3(#var);
This is a warning provided by MySQL. They can be a bit confusing, i suggest you read up on it: See http://dev.mysql.com/doc/refman/5./en/show-warnings.html
I would use this approach instead
declare v_var VARCHAR(200); <-- if that whats it expected to be
open cur;
-- create a loop
repeat_cur: LOOP
FETCH cur INTO var;
-- checks if it is done
if finished then
LEAVE repeat_cur;
end if;
// DO THE WORK
END LOOP;
close cur;
Im not sure since var is a expected out parameter. You can declare var as a variable and work with it, otherwise just skip the declare line i wrote.
Check out this page: How to get rid of "Error 1329: No data - zero rows fetched, selected, or processed" , he had the same problem, and was solved by adding a simple select statement into var.
If above doesnt work, try adding this before the end of the loop.
SELECT 'var' INTO var;

Multiple handlers conflicting

I have nested cursor loops, and I wanted to catch error 1329, no data fetch, on the outer loop. How can I do this?
I tried to add a second CONTINUE HANDLER for this outer loop cursor but it catches nested loop errors (not wanted), and it ends up not triggering the nested handler.
I have this:
DECLARE cur1 CURSOR FOR select data, valor_split, valor_div from tbl1 where data >= primeira_mov and id_papel = idpapel order by data DESC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE CONTINUE HANDLER FOR 1329 BEGIN
SET nodata_issue = 1;
SET dateof_issue = datasplit;
END;
Any ideas on how can I solve this?
Set a flag to 1 when you enter the inner loop, set it to 0 when you leave it.
Then:
DECLARE CONTINUE HANDLER FOR 1329 BEGIN
IF flag_innerloop = 0 THEN do_something;
ELSE do_something_else;
END;

How to use goto label in MySQL stored function

I would like to use goto in MySQL stored function.
How can I use?
Sample code is:
if (action = 'D') then
if (rowcount > 0) then
DELETE FROM datatable WHERE id = 2;
else
SET p=CONCAT('Can not delete',#b);
goto ret_label;
end if;
end if;
Label: ret_label;
return 0;
There are GOTO cases which can't be implemented in MySQL, like jumping backwards in code (and a good thing, too).
But for something like your example where you want to jump out of everything to a final series of statements, you can create a BEGIN / END block surrounding the code to jump out of:
aBlock:BEGIN
if (action = 'D') then
if (rowcount > 0) then
DELETE FROM datatable WHERE id = 2;
else
SET p=CONCAT('Can not delete',#b);
LEAVE aBlock;
end if;
end if;
END aBlock;
return 0;
Since your code is just some nested IFs, the construct is unnecessary in the given code. But it makes more sense for LOOP/WHILE/REPEAT to avoid multiple RETURN statements from inside a loop and to consolidate final processing (a little like TRY / FINALLY).
There is no GOTO in MySQL Stored Procs. You can refer to this post:
MySQL :: Re: Goto Statement

How to use nested loops and variables in MySQL statement

I'm trying to write a sql statement that will insert data given a few setup variables. I don't want to create a stored procedure, as it's not something I'll be dealing with anywhere except as an administrator and I don't want the stored procedure hanging around. I just want a statement that works. Here's what I have so far:
SET #app = 7;
SET #time = UNIX_TIMESTAMP(NOW());
SET #maxValue = 100;
SET #decrement = 10;
SET #category = 1;
SET #minSubcategory = 0;
SET #maxSubcategory = 19;
SET #subcategory = #minSubcategory;
subcat_loop: LOOP
SET #idx = 0;
insert_loop: LOOP
SET #id = CONCAT('TempId', #idx+1);
SELECT #name:=username FROM user WHERE id = #id;
SET #value = #maxValue - #decrement * #idx;
INSERT INTO data (userId, username, app, category, subcategory, value, date) VALUES
(#id, #name, #app, #category, #subcategory, #value, #time);
SET #idx = #idx+ 1;
IF #idx > 10 THEN
LEAVE insert_loop;
END IF;
END LOOP insert_loop;
SET #subcategory = #subcategory + 1;
IF #subcategory > #maxSubcategory THEN
LEAVE subcat_loop;
END IF;
END LOOP subcat_loop;
But it doesn't like the SET #idx = 0 inside the loop for some reason. What am I doing wrong?
Note that this is probably the first time I've tried doing anything this complicated with MySQL, and my little knowledge is probably more dangerous than being completely oblivious, so let me know if I'm going about this the wrong way completely (although I really, really don't want a stored procedure for this).
Unfortunately you can't use LOOP outside of a stored program: stored procedures, stored functions, and triggers.
You do have some options:
You can create a stored procedure and restrict the privileges so other users can't execute it.
Another option is to create a stored procedure temporarily in your script, run it, then drop it at the end of the script.
Otherwise, if you still don't want to create a stored procedure, your best bet is to write a small script in shell, python, etc to do your looping.
Good luck!