Mysql - How to split text variable in stored procedure - mysql

I have a MySQL variable as below.
DECLARE str TEXT DEFAULT '2014-01-02 13:00:00|2014-02-04 12:59:59#0#2014-02-04 13:00:00|2014-03-04 12:59:59#0#2014-03-04 13:00:00|2014-04-02 13:59:59#0#2014-04-02 14:00:00|2014-05-02 14:59:59#0#2014-05-02 15:00:00|2014-06-03 14:59:59';
I want to break this whole string first by using the separator #0# and from the results break the string using separator |.
I have tried MySQL split_str function but I am not able to do it.
Its giving me the error split_str does not exist.
Please suggest some other way to do this.

Finally i have resolved my problem using below procedure.
I am able to solve it using temporary table and procedure. I am no more using mysql variable for this. We can call the procedure as below....
CALL SplitString('2014-01-02 13:00:00|2014-02-04 12:59:59#0#2014-02-04 13:00:00|2014-03-04 12:59:59#0#2014-03-04 13:00:00|2014-04-02 13:59:59#0#2014-04-02 14:00:00|2014-05-02 14:59:59#0#2014-05-02 15:00:00|2014-06-03 14:59:59', '#0#', 'tblindex');
Here tblindex is temporary table i have used.
My procedure is below....
DELIMITER $$
DROP PROCEDURE IF EXISTS `SplitString`$$
CREATE PROCEDURE `SplitString`( IN input TEXT,IN delm VARCHAR(10),tblnm varchar(50))
BEGIN
DECLARE cur_position INT DEFAULT 1 ;
DECLARE remainder TEXT;
DECLARE cur_string VARCHAR(1000);
DECLARE delm_length TINYINT UNSIGNED;
set #sql_drop = concat("DROP TABLE IF EXISTS ",tblnm);
prepare st_drop from #sql_drop;
execute st_drop;
set #sql_create = concat("CREATE TEMPORARY TABLE ",tblnm," (value VARCHAR(2000) NOT NULL ) ENGINE=MEMORY;");
prepare st_create from #sql_create;
execute st_create;
SET remainder = input;
SET delm_length = CHAR_LENGTH(delm);
WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0
DO
SET cur_position = INSTR(remainder, delm);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
-- select cur_string;
IF TRIM(cur_string) != '' THEN
set #sql_insert = concat("INSERT INTO ",tblnm," VALUES ('",cur_string,"');");
prepare st_insert from #sql_insert;
execute st_insert;
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delm_length);
END WHILE;
END$$
DELIMITER ;

Related

Using a custom(user-defined) function inside a procedure in mysql

In the code below, there's a function that generates a random string, and a procedure that is supposed to insert random strings into a table called Users. I have successfully created the function and it's working without any problem, but when I try to create the procedure, it returns a syntax error at line "SET #str = SELECT randstring(8);" I think I am trying to call my function in a wrong way. I'm new to databases so please bear with me.
DELIMITER $$
CREATE FUNCTION `Randstring`(LENGTH SMALLINT(3)) RETURNS VARCHAR(100) CHARSET utf8
BEGIN
SET #returnStr='';
SET #allowedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
SET #i = 0;
WHILE (#i < LENGTH) DO
SET #returnStr = CONCAT(#returnStr, SUBSTRING(#allowedChars, FLOOR(RAND() * LENGTH(#allowedChars) + 1), 1));
SET #i = #i + 1;
END WHILE;
RETURN #returnStr;
END
DELIMITER $$
CREATE PROCEDURE insertdata()
BEGIN
SET #str='';
DECLARE i INT DEFAULT 0;
WHILE i <= 1000 DO
SET #str = SELECT randstring(8);
INSERT INTO Users (user_name)
VALUES(#str);
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
Presumably, you intend either:
SET #str = randstring(8);
Or:
SELECT #str := randstring(8);
Or:
SET #str = (SELECT #randstring(8));
A SELECT when used as a subquery needs a parentheses before it. However, no subquery is really necessary.

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

Incorrect Output in mysql split function

I have created mysql function to split the string in rows using temporary table, it gives correct in temp table, but not when i call the function it returns 1 as output.
My code is as below
DELIMITER $$
DROP FUNCTION IF EXISTS `split`$$
CREATE FUNCTION `split`(`String` VARCHAR(8000), `Delimiter` CHAR(1)) RETURNS VARCHAR(8000) CHARSET latin1
BEGIN
DECLARE idx INT;
DECLARE slice VARCHAR(8000);
DECLARE result INT DEFAULT 0;
DROP TEMPORARY TABLE IF EXISTS tmp;
CREATE TEMPORARY TABLE `tmp` (items VARCHAR(8000));
-- set #tmptab = tmp;
SET idx = 1;
label: WHILE LENGTH(`String`)<1 OR `String` IS NULL DO
LEAVE label;
END WHILE;
loop_lable: WHILE (idx<>0) DO
SET idx = LOCATE(`Delimiter`,`String`);
IF (idx<>0) THEN
SET slice = LEFT(`String`,idx - 1);
ELSE
SET slice = `String`;
END IF;
IF(LENGTH(slice)>0) THEN
INSERT INTO tmp(Items) VALUES(slice) ;
SET result = 1;
END IF;
SET `String` = RIGHT(`String`,LENGTH(`String`) - idx);
IF LENGTH(`String`) = 0 THEN
LEAVE loop_lable;
END IF;
END WHILE;
RETURN result;
END$$
DELIMITER ;

Compare String function in mysql by words

I am trying to create a search function in mysql. In order to make the search result more reliability i need to compare two string by words. Inputs are 2 strings and output is number word two strings match. In MySql i did as below.
CREATE DEFINER=`root`#`localhost` FUNCTION `CompareStrings`(str1 VARCHAR(255),str2 VARCHAR(255)) RETURNS double
BEGIN
DECLARE cur_position INT DEFAULT 1 ;
DECLARE remainder TEXT;
DECLARE cur_string VARCHAR(50);
DECLARE delimiter_length TINYINT UNSIGNED;
DECLARE numberMatch INT;
DECLARE total INT;
DECLARE result DOUBLE DEFAULT 0;
DECLARE delim VARCHAR(10);
DECLARE string2 VARCHAR(255);
SET delim = ' ';
DROP TEMPORARY TABLE IF EXISTS SplitString1;
CREATE TEMPORARY TABLE SplitString1 (
SplitString1ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT ,
val VARCHAR(50) NOT NULL
) ENGINE=MyISAM;
DROP TEMPORARY TABLE IF EXISTS SplitString2;
CREATE TEMPORARY TABLE SplitString2 (
SplitString1ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT ,
val VARCHAR(50) NOT NULL
) ENGINE=MyISAM;
SET remainder = str1;
SET delimiter_length = CHAR_LENGTH(delim);
WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0 DO
SET cur_position = INSTR(remainder, delim);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
IF TRIM(cur_string) != '' THEN
INSERT INTO SplitString1(val) VALUES (cur_string);
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delimiter_length);
END WHILE;
SET remainder = str2;
SET cur_position = 1;
WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0 DO
SET cur_position = INSTR(remainder, delim);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
IF TRIM(cur_string) != '' THEN
INSERT INTO SplitString2(val) VALUES (cur_string);
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delimiter_length);
END WHILE;
SELECT count(*) INTO numberMatch
FROM SplitString1 s1 JOIN SplitString2 s2 ON s1.val = s2.val;
RETURN result;
END
The idea is create two temporary table store each word and then compare these 2 tables. The result is good but the performace is awful. Anybody has better idea, please give me an advice.
Many thanks!
I don't think this will work as stated.
The logic is sound but you have not assigned any value to your result variable. Hence this function will always return 0. Replace:
RETURN result;
with
RETURN numberMatch;
Also replace:
CREATE DEFINER=`root`#`localhost` FUNCTION `CompareStrings`(str1 VARCHAR(255),str2 VARCHAR(255)) RETURNS double
with
CREATE DEFINER=`root`#`localhost` FUNCTION `CompareStrings`(str1 VARCHAR(255),str2 VARCHAR(255)) RETURNS double READS SQL DATA
As far as efficiency goes it looks pretty efficient. When you say 'performance is awful' - what constitutes 'awful'? Have you got any benchmark figures e.g. x calls took y millis?

Unable to create UDF in my sql

Unable to create UDF. Am getting below error at the time of creation
Error: 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 ';
CREATE FUNCTION `seat_count`(seatno varchar(250))
RETURNs varchar(250)
BEG' at line 1
code: http://pastebin.com/uf4DkXZh
code:
CREATE FUNCTION `seat_count`(seatno VARCHAR(250))
RETURNS VARCHAR(250)
BEGIN
SET #str= REPLACE(seatno, ',', '');
SET #stcnt=CHAR_LENGTH(str);
SET #x=1;
SET #result;
WHILE (#x <= #stcnt)
DO
SET #st=SUBSTRING_INDEX(#str,',',X);
IF ((LENGTH(#seatno) - LENGTH(REPLACE(#seatno, st, '')))/LENGTH(#st)=1)
THEN SET #result=CONCAT(#st,#result);
END IF;
SET #x=#x+1;
END WHILE;
RETURN #result;
END$$
When you develop a stored procedure in MySQL, you can pass the input parameters and declare the local variables, the local variable are not prepended with any prefixes unlike user-defined variable which are prepended with #. For detail procedure vs user-defined variable
DELIMITER $$
CREATE FUNCTION `SEAT_COUNT`(`seatno` VARCHAR(250)) RETURNS VARCHAR(250)
DETERMINISTIC
BEGIN
DECLARE result VARCHAR(250);
SET #str = REPLACE(seatno, ',', '');
SET #stcnt = CHAR_LENGTH(#str);
SET #x = 1;
WHILE (#x <= #stcnt)
DO
SET #st = SUBSTRING_INDEX(#str,',',X);
IF ((LENGTH(#seatno) - LENGTH(REPLACE(#seatno, st, '')))/LENGTH(#st)=1)
THEN SET result = CONCAT(#st, #result);
END IF;
SET #x = #x+1;
END WHILE;
RETURN result;
END$$
DELIMITER ;
You have defined the result variable as user-defined e.g SET #result instead of local variable e.g DECLARE result VARCHAR(250)
I hope this will work at your end too.