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
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With