Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split string into two columns

I have the following string to split into two columns:

Given:

DECLARE @String VARCHAR(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5'

I want to split it into two columns:

column1  column2
-----------------
Mak      1
Jak      2
Smith    3
Lee      4
Joseph   5

My try:

Table-valued Function:

CREATE FUNCTION [dbo].[udf_Split]
(
@InputString VARCHAR(8000), 
@Delimiter VARCHAR(50)
)
RETURNS @Items TABLE (ID INTEGER IDENTITY(1,1), Item VARCHAR(8000))

AS
BEGIN
      IF @Delimiter = ' '
      BEGIN
            SET @Delimiter = ','
            SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
      END
      IF (@Delimiter IS NULL OR @Delimiter = '')
            SET @Delimiter = ','

      DECLARE @Item VARCHAR(8000)
      DECLARE @ItemList VARCHAR(8000)
      DECLARE @DelimIndex INT

      SET @ItemList = @InputString
      SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
      WHILE (@DelimIndex != 0)
      BEGIN
            SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
            INSERT INTO @Items VALUES (@Item)

            SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
            SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
      END -- End WHILE

      IF @Item IS NOT NULL 
      BEGIN
            SET @Item = @ItemList
            INSERT INTO @Items VALUES (@Item)
      END

      ELSE INSERT INTO @Items VALUES (@InputString)

      RETURN

END 

Function calling:

SELECT Item FROM [dbo].[udf_Split](@String ,',');

Output:

Item
--------------
Mak^1
Jak^2
Smith^3
Lee^4
Joseph^5
like image 593
MAK Avatar asked Feb 03 '26 08:02

MAK


2 Answers

First, Please note that SQL Server 2008 r2 is out of extended support. It's high time to upgrade to a newer version.

For a single string, I would probably use a little dynamic SQL magic trick:

DECLARE @String VARCHAR(MAX) = 'Mak^1,Jak^2,Smith^3,Lee^4,Joseph^5'

DECLARE @Sql VARCHAR(MAX) = 'SELECT Name,Id FROM (VALUES (''' + REPLACE(REPLACE(REPLACE(@String,'''',''''''), ',', '),('''), '^', ''',') + ')) V(Name, Id)';

-- @Sql now contains this:
-- SELECT Name,Id FROM (VALUES ('Mak',1),('Jak',2),('Smith',3),('Lee',4),('Joseph',5)) V(Name, Id)

EXEC(@Sql)

Results:

Name    Id
Mak     1
Jak     2
Smith   3
Lee     4
Joseph  5
like image 168
Zohar Peled Avatar answered Feb 05 '26 21:02

Zohar Peled


In the most recent versions of SQL Server, you can use string_split():

select left(s.value, charindex('^', value) - 1) as column1,
       stuff(s.value, 1, charindex('^', value), '') as column2
from string_split(@string, ',') s ;

You might find it most convenient to download a split function to handle this.

Otherwise, I think a recursive CTE is a simple enough approach:

with cte as (
      select convert(varchar(max), null) as row,
             @string as str
      union all
      select convert(varchar(max), left(str, charindex(',', str + ',') - 1)),
             convert(varchar(max), stuff(str, 1, charindex(',', str + ','), ''))
      from cte
      where str <> '' 
     )
select left(cte.row, charindex('^', cte.row) - 1) as column1,
       stuff(cte.row, 1, charindex('^', cte.row), '')
from cte
where row is not null;

Here is a db<>fiddle.

like image 26
Gordon Linoff Avatar answered Feb 05 '26 20:02

Gordon Linoff