Error in SET command in a MySQL Procedure - mysql

I wish to retrieve all distinct values of a column (Task in this case) from a table (dataset in this case). The task values will go as column name for the table that I intend to create using the procedure (albeit not defined currently but only printed). But it gives an error at the line
SET qry = CONCAT("CREATE TABLE ",tblname," ( TEAM varchar(20) PRIMARY KEY ," );
saying end was missing. When I put end it says semicolon is missing and vice-versa.
DELIMITER //
CREATE PROCEDURE `createTable` (IN tblName varchar(20))
BEGIN
DECLARE task varchar(20) DEFAULT "";
DECLARE exit_loop BOOLEAN;
SET qry = CONCAT("CREATE TABLE ",tblname," ( TEAM varchar(20) PRIMARY KEY ," );
DECLARE task_curs CURSOR FOR SELECT DISTINCT Task FROM dataset;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN task_curs;
my_loop: loop
FETCH task_curs into task;
qry=CONCAT(qry,task, ' INT DEFAULT 0, ');
IF exit_loop THEN
CLOSE task_curs;
LEAVE my_loop;
END IF;
END LOOP my_loop;
qry=TRIM(TRAILING ',' FROM qry);
qry=CONCAT(qry, ');');
SELECT qry;
END; //
DELIMITER ;
What might be possibly wrong with the syntax ? Thanks!

Try:
DELIMITER //
CREATE PROCEDURE `createTable` (IN tblName varchar(20))
BEGIN
DECLARE task varchar(20) DEFAULT "";
DECLARE exit_loop BOOLEAN;
DECLARE qry VARCHAR(500);
-- SET qry = CONCAT("CREATE TABLE ",tblname," ( TEAM varchar(20) PRIMARY KEY ," );
DECLARE task_curs CURSOR FOR SELECT DISTINCT Task FROM dataset;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
SET qry = CONCAT("CREATE TABLE ",tblname," ( TEAM varchar(20) PRIMARY KEY ," );
OPEN task_curs;
my_loop: loop
FETCH task_curs into task;
-- qry=CONCAT(qry,task, ' INT DEFAULT 0, ');
-- SET qry=CONCAT(qry,task, ' INT DEFAULT 0, ');
IF exit_loop THEN
CLOSE task_curs;
LEAVE my_loop;
END IF;
SET qry=CONCAT(qry,task, ' INT DEFAULT 0, ');
END LOOP my_loop;
-- qry=TRIM(TRAILING ',' FROM qry);
SET qry=TRIM(TRAILING ',' FROM qry);
-- qry=CONCAT(qry, ');');
SET qry=CONCAT(qry, ');');
SELECT qry;
END; //
DELIMITER ;

Related

Pass a variable into CURSOR's SELECT Query (MySQL)

I'm trying the stored procedure below. However, when i pass the actual column name in 'DECLARE cur1' line, the SP returns correct value but when I pass variable name i.e. input parameter (colName), it returns 0. I've added comments in my code below. Is the code correct?
DROP PROCEDURE IF EXISTS test1.checkHardcodedField;
CREATE PROCEDURE test1.checkHardcodedField(IN textValue CHAR(10), colName CHAR(10), OUT counter VARCHAR(100))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE temp CHAR(16);
DECLARE i INT DEFAULT 0;
-- Issue with this statement, returns incorrect value.
DECLARE cur1 CURSOR FOR SELECT colName FROM data1;
-- This statement works. MSH3 is actual column name
-- DECLARE cur1 CURSOR FOR SELECT MSH3 FROM data1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO temp;
IF done THEN
LEAVE read_loop;
END IF;
IF temp = textValue THEN
SET i = i + 1;
END IF;
END LOOP;
SET counter = i;
CLOSE cur1;
END;
CREATE PROCEDURE procedure_name (..., fieldname VARCHAR, ...)
BEGIN
CREATE TEMPORARY TABLE tmp (field VARCHAR(10));
SET #sql := CONCAT('INSERT INTO tmp SELECT ', fieldname, ' FROM tablename;');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DROP PREPARE stmt;
BEGIN
DECLARE cur CURSOR FOR SELECT field FROM tmp;
...
END;
DROP TABLE tmp;
END

MySQL said: #1338 - Cursor declaration after handler declaration

I'm on developing web project and i get some problem with migration from oracle database to mysql database. I want to create function with this code :
DROP FUNCTION IF EXISTS F_MANIFEST_GABUNG_SMR;
DELIMITER //
CREATE FUNCTION F_MANIFEST_GABUNG_SMR (input_val varchar(4000))
RETURNS VARCHAR(4000)
BEGIN
DECLARE return_text VARCHAR(10000) DEFAULT NULL;
DECLARE not_found INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found = 1;
DECLARE x CURSOR FOR SELECT DISTINCT IFNULL(SMR,'-') SMR FROM MANIFEST_EDI_SMR WHERE BL_NBR = input_val; OPEN x;
FETCH x INTO;
WHILE NOT_FOUND=0
DO
SET return_text = concat(ifnull(return_text, '') , ' ' , IFNULL(x.SMR, '')) ;
FETCH INTO;
END WHILE;
CLOSE ;
IF char_length(return_text) > 85 THEN
SET return_text = concat(ifnull(substr(return_text,1,85), '') , ' detail asp BL');
END IF;
RETURN return_text;
END;
//
DELIMITER ;
I am using phpmyadmin to store function with routine. Thanks for your help :)
The error message is self explanatory:you have declare the cursor after handler,need to change the order:
DROP FUNCTION IF EXISTS F_MANIFEST_GABUNG_SMR;
DELIMITER //
CREATE FUNCTION F_MANIFEST_GABUNG_SMR (input_val varchar(4000))
RETURNS VARCHAR(4000)
BEGIN
DECLARE return_text VARCHAR(10000) DEFAULT NULL;
DECLARE not_found INT DEFAULT 0;
-- Declare cursor before handler
DECLARE x CURSOR FOR SELECT DISTINCT IFNULL(SMR,'-') SMR
FROM MANIFEST_EDI_SMR WHERE BL_NBR = input_val; OPEN x;
-- handler need to be after cursor
DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found = 1;
FETCH x INTO;
WHILE NOT_FOUND=0
DO
SET return_text = concat(ifnull(return_text, '') , ' ' , IFNULL(x.SMR, '')) ;
FETCH INTO;
END WHILE;
CLOSE ;
IF char_length(return_text) > 85 THEN
SET return_text = concat(ifnull(substr(return_text,1,85), '') , ' detail asp BL');
END IF;
RETURN return_text;
END;
//
DELIMITER ;
More details can be found at:https://dev.mysql.com/doc/refman/8.0/en/cursors.html

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: Reversed GROUP_CONCAT failed. What's wrong?

I have a table "source" with columns id and contents.
|id|contents|
|1|Digestion is the process of turning food into fuel for energy|
|2|During the digestive process, food passes down the throat|
|3|The health of your digestive system has a lot to do with lifestyle|
I want to explode this by space.
Here is my script in MySQL workbench:
CREATE PROCEDURE explode_table ()
BEGIN
DECLARE idparagraf INTEGER;
DECLARE paragraf TEXT;
DECLARE i INTEGER;
DECLARE h INTEGER;
DECLARE Frase TEXT;
DECLARE input_text TEXT;
DECLARE segmenter VARCHAR(45);
DECLARE exit_loop BOOLEAN default FALSE;
DECLARE my_cursor CURSOR FOR SELECT id, contents FROM source;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
SET h=0;
SET i=0;
SET exit_loop=FALSE;
SET segmenter=REPLACE(segmenter, ' ', ' ');
SET input_text=REPLACE(input_text, ' ', ' ');
CREATE TEMPORARY TABLE WordList
(
ID INTEGER AUTO_INCREMENT NOT NULL,
IdParagraph INTEGER,
Words TEXT,
PRIMARY KEY (ID)
);
OPEN my_cursor;
RowByRow : LOOP
FETCH my_cursor INTO idparagraf, paragraf;
IF exit_loop THEN
SELECT * FROM WordList;
CLOSE my_cursor;
LEAVE RowByRow;
END IF;
REPEAT
SET i=i+1;
SET Frase = split_string(paragraf,' ', i);
INSERT INTO WordList
(ID, IdParagraph, Words)
VALUES
(0, idparagraf, Frase);
UNTIL i = ComplexCount(paragraf,' ')
END REPEAT;
SELECT * FROM WordList;
END LOOP RowByRow;
END
Problem probably lies on DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE; or "IF exit_loop THEN" or else?
Your help will be appreciated. Please help

how to do a split on a sql table column

I have a table that stores some comma separated strings. Is there a way to write a sql to
return me a separate rows for each token string obtained by splitting across commas.
You can simply write and call a stored procedure
DELIMITER $$
DROP PROCEDURE IF EXISTS explode_table $$
CREATE PROCEDURE explode_table(bound VARCHAR(255))
BEGIN
DECLARE id INT DEFAULT 0;
DECLARE value TEXT;
DECLARE occurance INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE splitted_value INT;
DECLARE done INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT table1.id, table1.value
FROM table1
WHERE table1.value != '';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS table2;
CREATE TEMPORARY TABLE table2(
`id` INT NOT NULL,
`value` VARCHAR(255) NOT NULL
) ENGINE=Memory;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO id, value;
IF done THEN
LEAVE read_loop;
END IF;
SET occurance = (SELECT LENGTH(value)
- LENGTH(REPLACE(value, bound, ''))
+1);
SET i=1;
WHILE i <= occurance DO
SET splitted_value =
(SELECT REPLACE(SUBSTRING(SUBSTRING_INDEX(value, bound, i),
LENGTH(SUBSTRING_INDEX(value, bound, i - 1)) + 1), ',', ''));
INSERT INTO table2 VALUES (id, splitted_value);
SET i = i + 1;
END WHILE;
END LOOP;
SELECT * FROM table2;
CLOSE cur1;
END; $$
-------------------
CALL explode_table(',');