5

I have String asdasdwdfef,rgrgtggt,weef and i want output like in table format as shown below

id      decription
1       asdasdwdfef
2       rgrgtggt
3       weef

For this i created a procedure here is my procedure

DELIMITER ;;
CREATE Procedure Split(_RowData text, _Delimeter text)
BEGIN
    DECLARE _Iterator INT default 1;
    DECLARE _FoundIndex INT;
    DECLARE _Data varchar(255);
    SET _FoundIndex = LOCATE(_Delimeter,_RowData);
    DROP TABLE IF EXISTS _RtnValue;
    CREATE temporary TABLE _RtnValue(ID INT AUTO_INCREMENT NOT NULL, description text, primary key(ID));
    WHILE _FoundIndex > 1 DO
        INSERT INTO _RtnValue (description)
        SELECT
        _Data = LTRIM(RTRIM(SUBSTRING(_RowData, 1, _FoundIndex - 1)));
        set _RowData = SUBSTRING(_RowData, _FoundIndex + LENGTH(_Delimeter) / 2, LENGTH(_RowData));
        SET _Iterator = _Iterator + 1;
        SET _FoundIndex = LOCATE(_Delimeter, _RowData);
    END WHILE;
    INSERT INTO _RtnValue(description) SELECT _Data = LTRIM(RTRIM(_RowData));
    select * from _RtnValue;
END

But when i execute it by using following command

call Split('asdasdwdfef,rgrgtggt,weef', ',');

it gives me the following output:

id      decription
1       NULL
2       NULL
3       NULL

Please let me know how to fix this issue. I am using MySQL.

7
  • 1
    @user1515791 I declare my _data "DECLARE _Data varchar(255);" and error is out but the output is NULL. Commented May 10, 2016 at 5:34
  • 1
    @user1515791 i just update my post please check it again. Commented May 10, 2016 at 5:38
  • 1
    Maybe interesting? sqlfiddle.com/#!9/007e3/4. You may need to copy the code to your IDE. It uses functions to parse the string. And a 'table of integers' to generate the rows. Commented May 11, 2016 at 3:14
  • 1
    @RyanVincent why not post that as an answer with explanation? Commented May 14, 2016 at 14:48
  • 1
    @RyanVincent can you just explain why my description values NULL. Commented May 14, 2016 at 15:48

2 Answers 2

2

I got the answer

First create new function

CREATE FUNCTION SPLIT_STR(x VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1), delim, '');

Then create stored procedure

DELIMITER ;;
CREATE PROCEDURE Split(in fullstr varchar(255))
BEGIN
    DECLARE a INT Default 0 ;
    DECLARE str VARCHAR(255);

    DROP TABLE IF EXISTS my_temp_table;
    CREATE temporary TABLE my_temp_table(ID INT AUTO_INCREMENT NOT NULL, description text, primary key(ID));

    simple_loop: LOOP
        SET a=a+1;
        SET str=SPLIT_STR(fullstr,",",a);
        IF str='' THEN
            LEAVE simple_loop;
        END IF;
        #Do Inserts into temp table here with str going into the row
        insert into my_temp_table (description) values (str);
   END LOOP simple_loop;
   select * from my_temp_table;
END

After that when i call it by call Split('asas,d,sddf,dfd'); it gives me the output that what i want.

Thanx for every suggestion.

Sign up to request clarification or add additional context in comments.

Comments

1
+50

Requirements: split a 'delimited' column into rows (a table).

Why? You can use all the SQL Aggregate functions to process the rows.

Working SQLFiddle

Related questions that use this code:

I chose to use:

  • table of integers (integersequence) which when 'inner joined' or 'cross joined' (same thing) to another table will generate rows which are certain to have a unique sequence number starting from 1. This is just using what RDBMS engines are required to do.

  • why a table of integers?: It is small and will get loaded into the cache. It is easy to understand.

  • Rather than have lots of code in the query that obscures what it actually does. I use functions that do one job. It simplifies the main query and can be tested and checked separately. I am only concerned about ease of maintenance and understanding at this point.

The example here is for one string. However, It can be easily expanded to a table of delimited strings of various sizes. The 'cross join' will create all the possible options of index starting from 1 when joining to integersequence (i really need to use another name :-/).

So, the query:

SET @StrToParse = "asdasdwdfef,rgrgtggt,weef";

/* example */
select integerseries.id,
       count_in_set(@StrToParse, ','),
       value_in_set(@StrToParse, ',', integerseries.id)
from integerseries
where integerseries.id <= count_in_set(@StrToParse, ',');

The output:

PositionOfString, CountOfCommaDelimitedStrings, StringAtThatPosition 

1                 3                             asdasdwdfef
2                 3                             rgrgtggt
3                 3                             weef

Now, how do we get those values:

I chose to use two functions:

The names are related to the mysql function 'FIND_IN_SET'.

1) The COUNT_IN_SET function: returns the count of character delimited items in the column.

CREATE FUNCTION `COUNT_IN_SET`(haystack VARCHAR(1024), 
                               delim CHAR(1)
                               ) RETURNS INTEGER
BEGIN
      RETURN CHAR_LENGTH(haystack) - CHAR_LENGTH( REPLACE(haystack, delim, '')) + 1;
END$$

2) The VALUE_IN_SET function: treats the delimited list as a one based array and returns the value at the given 'index'.

CREATE FUNCTION `VALUE_IN_SET`(haystack VARCHAR(1024), 
                               delim CHAR(1), 
                               which INTEGER
                               ) RETURNS VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci
BEGIN
      RETURN  SUBSTRING_INDEX(SUBSTRING_INDEX(haystack, delim, which),
                     delim,
                     -1);
END$$

The intereseries table - see (Tally tables)

CREATE TABLE `integerseries` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `integerseries` */

insert  into `integerseries`(`id`) values (1);
insert  into `integerseries`(`id`) values (2);
insert  into `integerseries`(`id`) values (3);
insert  into `integerseries`(`id`) values (4);
insert  into `integerseries`(`id`) values (5);
insert  into `integerseries`(`id`) values (6);
insert  into `integerseries`(`id`) values (7);
insert  into `integerseries`(`id`) values (8);
insert  into `integerseries`(`id`) values (9);
insert  into `integerseries`(`id`) values (10);

3 Comments

thanx for your post, but i got the answer.
@user3441151, I am pleased you got an answer you are happy with.
Thank you for the bonus. It is appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.