I already answered an incredibly similar question today, so look at the answer:
SQL comma column => to rows, then sum total?
but try the following:
I prefer a number table approach to split a string in TSQL
For this method to work, you need to complete this setup at once:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number INTO Numbers FROM sys.objects s1 CROSS JOIN sys.objects s2 ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Once the Numbers table is configured, create this split function:
CREATE FUNCTION [dbo].[FN_ListToTable] ( @SplitOn char(1) --REQUIRED, the character to split the @List string on ,@List varchar(8000)--REQUIRED, the list to split apart ) RETURNS TABLE AS RETURN ( ---------------- --SINGLE QUERY-- --this will not return empty rows ---------------- SELECT ListValue FROM (SELECT LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue FROM ( SELECT @SplitOn + @List + @SplitOn AS List2 ) AS dt INNER JOIN Numbers n ON n.Number < LEN(dt.List2) WHERE SUBSTRING(List2, number, 1) = @SplitOn ) dt2 WHERE ListValue IS NOT NULL AND ListValue!='' ); GO
Now you can easily split the CSV row into a table and join it:
select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,')
CONCLUSION:
ListValue ----------------------- 1 2 3 4 5 6777 (6 row(s) affected)
Now you can use CROSS APPLY to split each row in the table, for example:
DECLARE @YourTable table (RowID int, RowValue varchar(200)) INSERT INTO @YourTable VALUES (1,'KEY11:VALUE11;KEY12:VALUE12;KEY13:VALUE13') INSERT INTO @YourTable VALUES (2,'KEY21:VALUE21;KEY22:VALUE22;KEY23:VALUE23') INSERT INTO @YourTable VALUES (3,'KEY31:VALUE31;KEY32:VALUE32;KEY33:VALUE33') SELECT o.RowID,RIGHT(st.ListValue,LEN(st.ListValue)-CHARINDEX(':',st.ListValue)) AS RowValue FROM @YourTable o CROSS APPLY dbo.FN_ListToTable(';',o.RowValue) AS st
CONCLUSION:
RowID ----------- ------- 1 VALUE11 1 VALUE12 1 VALUE13 2 VALUE21 2 VALUE22 2 VALUE23 3 VALUE31 3 VALUE32 3 VALUE33 (9 row(s) affected)