Procedure in MySQL with LOOP - mysql

I'm really struggling with this LOOP in my procedure. I can't understand what the error means. I guess anyone can just try to run this without any knowledge of the database...
DROP PROCEDURE IF EXISTS removeDuplicates;
DELIMITER $$
CREATE PROCEDURE removeDuplicates(str TEXT)
BEGIN
DECLARE temp_word TEXT;
DECLARE last_word TEXT;
DECLARE result TEXT;
DECLARE finished INT DEFAULT false;
DECLARE words_cursor CURSOR FOR
SELECT word FROM explosion;
DECLARE CONTINUE handler FOR NOT found
SET finished = true;
CALL explode(str);
DROP TABLE IF EXISTS temp_words;
CREATE TABLE temp_words (id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, t VARCHAR(100));
OPEN words_cursor;
loop_words: LOOP
FETCH words_cursor INTO temp_word;
IF finished THEN
LEAVE loop_words;
IF temp_word = "" THEN
SET result = CONCAT(result, temp_word, " ");
SET last_word = temp_word;
ELSEIF last_word = temp_word THEN
SET last_word = temp_word;
ELSE
INSERT INTO temp_words (t) VALUES (temp_word);
END IF;
END LOOP loop_words;
CLOSE words_cursor;
RETURN result;
END$$
DELIMITER ;
Any pointers would be gratefully received. The error I am getting is:
[ERROR in query 2] You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LOOP loop_words;
CLOSE words_cursor;
RETURN result;
END' at line 29
I'm sure it must be something simple, but I'll be damned if I can work it out.
Thanks, Chris

DROP PROCEDURE IF EXISTS removeDuplicates;
DELIMITER $$
CREATE PROCEDURE removeDuplicates(str TEXT , OUT OUT_STR_RESULT TEXT)
BEGIN
DECLARE temp_word TEXT;
DECLARE last_word TEXT;
DECLARE result TEXT;
DECLARE finished INT DEFAULT false;
DECLARE words_cursor CURSOR FOR
SELECT word FROM explosion;
DECLARE CONTINUE handler FOR NOT found
SET finished = true;
CALL explode(str);
DROP TABLE IF EXISTS temp_words;
CREATE TABLE temp_words (id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, t VARCHAR(100));
OPEN words_cursor;
loop_words: LOOP
FETCH words_cursor INTO temp_word;
IF finished THEN
LEAVE loop_words;
IF temp_word = "" THEN
SET result = CONCAT(result, temp_word, " ");
SET last_word = temp_word;
ELSEIF last_word = temp_word THEN
SET last_word = temp_word;
ELSE
INSERT INTO temp_words (t) VALUES (temp_word);
END IF;
END IF; -- i had made changes at this line.
END LOOP loop_words;
CLOSE words_cursor;
SET OUT_STR_RESULT =result;
-- RETURN result;
END$$
;
You missed one END IF.
One more thing: you can't put RETURN statement in procedure; it's only allowed in FUNCTION. Instead of that you can use OUT parameter for same.
Try above code.

Related

Return empty table after rollback

Im writing a procedure, I want it to return table if there wasnt any rollbacks, and return empty table / nothing if there was at least 1 rollback.
DELIMITER $$
CREATE PROCEDURE payment(IN amount int, IN profession varchar(50))
BEGIN
DECLARE done BOOL DEFAULT FALSE;
DECLARE salary INT;
DECLARE pes VARCHAR(11);
DECLARE summary INT DEFAULT 0;
DECLARE employee_cursor CURSOR FOR (SELECT RIGHT(PESEL,3), pensja FROM Pracownicy WHERE zawod=profession);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DROP TEMPORARY TABLE IF EXISTS tmp1;
CREATE TEMPORARY TABLE tmp1(pesel char(11), status varchar(20) DEFAULT 'wyplacono');
SET AUTOCOMMIT =0;
START TRANSACTION;
OPEN employee_cursor;
readLoop : LOOP
FETCH employee_cursor INTO pes,salary;
IF done THEN
LEAVE readLoop;
END IF;
SET summary = summary + salary;
IF( summary > amount ) THEN
ROLLBACK;
END IF;
INSERT INTO tmp1(pesel) VALUES(CONCAT('********',pes));
END LOOP;
CLOSE employee_cursor;
COMMIT;
SELECT * from tmp1;
END $$
DELIMITER ;
As far it works fine when it doesnt rollback, but
INSERT INTO tmp1(pesel) VALUES(CONCAT('********',pes));
seems to ignore transaction :/
move the rollback test to outside the loop.

MySQL Syntax Error - END IF line

I try to create a stored procedure with an if statement within.
I copied from: https://dev.mysql.com/doc/refman/5.7/en/local-variable-scope.html
But I get the following error exact on the END IF; near '':
DROP PROCEDURE IF EXISTS `myProc`;
CREATE DEFINER=`root`#`%` PROCEDURE `myProc`(
IN in_userId int,
IN in_projectId int
)
BEGIN
DECLARE tmp_courseId int;
DECLARE done TINYINT DEFAULT 0;
DECLARE cursorProjectCourse CURSOR FOR SELECT CourseId FROM XC_PROJECT_COURSE where projectId = in_projectId ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cursorProjectCourse;
read_loop: LOOP
FETCH FROM cursorProjectCourse INTO tmp_courseId;
IF done = 1 THEN LEAVE read_loop;
END IF;
SELECT tmp_courseId, in_userId;
END LOOP;
CLOSE cursorProjectCourse;
END;
Has anyone an idea where I make a mistake?
Exact error message:
SQL Error [1064] [42000]: You have an error in your SQL syntax; check
the manual that corresponds to your MySQL server version for the right
syntax to use near '' at line 19 SQL Error
MySQL Version:
5.5.46
Thanks for help!
I found the solution.
I have to set DELIMITER $$ at first statement and at the end DELIMITER ;
DELIMITER $$;
DROP PROCEDURE IF EXISTS `myProc`; $$
CREATE DEFINER=`root`#`%` PROCEDURE `myProc`(
IN in_userId int,
IN in_projectId int
)
BEGIN
DECLARE tmp_courseId int;
DECLARE done TINYINT DEFAULT 0;
DECLARE cursorProjectCourse CURSOR FOR SELECT CourseId FROM XC_PROJECT_COURSE where projectId = in_projectId ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cursorProjectCourse;
read_loop: LOOP
FETCH FROM cursorProjectCourse INTO tmp_courseId;
IF done = 1 THEN LEAVE read_loop;
END IF;
SELECT tmp_courseId, in_userId;
END LOOP;
CLOSE cursorProjectCourse;
END;$$
DELIMITER ;
It is important to set the keyword on the first position in line. If there is a blank on the first position, the error above will be thrown.
Well you are missing the loop label while ending loop. Change it to below
read_loop: LOOP
FETCH FROM cursorProjectCourse INTO tmp_courseId;
IF done = 1 THEN
LEAVE read_loop;
END IF;
END LOOP read_loop;
SELECT tmp_courseId, in_userId;

Can't find where is the MySQL syntax error

delimiter %%
create procedure getFileID(in fname varchar(100), out fId int)
begin
select ID from File
where Name = fname
into fId;
end %%
delimiter ;
delimiter $$
create procedure FileINFO(in fname varchar(100))
begin
declare SMS_done, Par_don boolean default false;
declare SMSID int;
declare SMSName varchar(100) default "";
declare SMSCode varchar(100) default "";
declare ParamName varchar(100) default "";
declare fId int default 0;
call getFileID(fname, fId);
declare c1 cursor for select ID, Code, Name from SMSTemplate where F_ID = fId;
declare continue handler for not found set SMS_done = true;
open c1;
SMS_loop : loop
fetch from c1 into SMSID, SMSCode, SMSName;
if SMS_done then
close c1;
leave SMS_loop;
end if;
block2 : begin
declare c2 cursor for
select Name from ParameterType where ST_ID = SMSID;
declare continue handler for not found set Par_done = true;
open c2;
Par_loop : loop
fetch from c2 into ParamName;
if SMS_done then
set SMS_done = false;
close c2;
leave Par_loop;
end if;
insert into FileDetails
(FileName, SMSName, SMSCode, ParamName)
values
(fname, SMSName, SMSCode, ParamName);
end loop Par_loop;
end block2;
end loop SMS_loop;
select * from FileDetails;
end $$
delimiter ;
and i get that error
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for
the right syntax to use
near 'declare c1 cursor for select ID, Code, Name from SMSTemplate where F_ID = fId;' at line 10
for starters get the declares all grouped together at the top.
Also there is no such thing as fetch into so those two things were fixed.
Par_don / Par_done had a typo in the declare.
Also, for sanity, have a drop if exist for the stored proc right above each one, so it is easily scripted and maintained.
drop procedure if exists FileINFO;
delimiter $$
create procedure FileINFO(in fname varchar(100))
begin
declare SMS_done, Par_done boolean default false;
declare SMSID int;
declare SMSName varchar(100) default "";
declare SMSCode varchar(100) default "";
declare ParamName varchar(100) default "";
declare fId int;
declare c1 cursor for select ID, Code, Name from SMSTemplate where F_ID = fId;
declare continue handler for not found set SMS_done = true;
call getFileID(fname, fId );
open c1;
SMS_loop : loop
fetch c1 into SMSID, SMSCode, SMSName;
if SMS_done then
close c1;
leave SMS_loop;
end if;
block2 : begin
declare c2 cursor for
select Name from ParameterType where ST_ID = SMSID;
declare continue handler for not found set Par_done = true;
open c2;
Par_loop : loop
fetch from c2 into ParamName;
if SMS_done then
set SMS_done = false;
close c2;
leave Par_loop;
end if;
insert into FileDetails
(FileName, SMSName, SMSCode, ParamName)
values
(fname, SMSName, SMSCode, ParamName);
end loop Par_loop;
end block2;
end loop SMS_loop;
select * from FileDetails;
end $$
delimiter ;
Does the table SMSTemplate have a field F_ID??
If not, that could be why you're getting this error.

MySql Procedure not returning value

I'm unable to get the result of OUT variable in this code, am I doing wrong something? can anyone help?
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE cid INT(10);
DECLARE cuserid VARCHAR(50);
DECLARE cur1 CURSOR FOR SELECT id,username FROM tblcustomer;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO cid,cuserid;
IF done THEN
LEAVE read_loop;
END IF;
SET customers_list = CONCAT(customers_list,cid,':',cuserid,',');
END LOOP;
CLOSE cur1;
END
The procedure prototype is missing from your snippet, but assuming the below:
CREATE PROCEDURE foo(OUT customers_list VARCHAR(100))
BEGIN
...
SET customers_list = 'foo-list';
END ;
This is how you would retreive your "return value":
CALL foo(#var);
SELECT #var; -- outputs "foo-list"
Strictly speaking, a procedure has no "return value". A function has:
CREATE FUNCTION bar() RETURNS VARCHAR(100)
BEGIN
...
RETURN 'bar-list';
END ;
SELECT bar(); -- outputs "bar-list";

How to replace a string with another in whole tables in a mysql database

I want to replace a string with another in full database. Assume database name is "A" and it contains 101 tables. I want to change "subhojit" to "jeet" in all table's column if it contains "subhojit".
Is it possible in MySql?
Need to write procedure?
Please reply.
update thetable set thecol = replace(thecol, 'subhojit', 'jeet')
where thecol like '%subhojit%';
From here.
This is a bit rough and ready (exception handling for example). But hopefully you can tidy it up for your own purposes:
DELIMITER $$
CREATE PROCEDURE `replace_value_in_all_cols`(IN i_schema varchar(250),IN i_fromVal varchar(250),IN i_toVal varchar(250), OUT o_errMessage varchar(250))
BEGIN
ALL_TEXT_COLUMNS : BEGIN
DECLARE noMoreRows boolean;
DECLARE db varchar(250);
DECLARE tbl varchar(250);
DECLARE col varchar(250);
DECLARE allTextCols CURSOR FOR
select c.table_schema,c.table_name,c.column_name
from information_schema.columns c
where c.table_schema = i_schema
and lower(data_type) in ('char','text','varchar');
DECLARE EXIT HANDLER for SQLEXCEPTION set o_errMessage := "Some error message";
declare continue handler for not found set noMoreRows := true;
open allTextCols;
UPDATE_LOOP : loop
fetch allTextCols
into db,tbl,col;
if noMoreRows then
close allTextCols;
leave UPDATE_LOOP;
end if;
SET #update_stmt:=CONCAT("UPDATE ",db,".",tbl," SET ",col," = replace(",col,",'",i_fromVal,"','",i_toVal,"');");
PREPARE update_stmt FROM #update_stmt;
EXECUTE update_stmt;
DEALLOCATE PREPARE update_stmt;
end loop UPDATE_LOOP;
END ALL_TEXT_COLUMNS;
END$$
DELIMITER ;
Then you can do something like:
call `replace_value_in_all_cols`("A",'subhojit','jeet', #err);