STRING_SPLIT in SQL Server 2012
Other approach is to use XML
Method with CROSS APPLY
to split your Comma Separated Data :
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA
FROM
(
SELECT CAST(''+REPLACE(@ID, ',', ' ')+' ' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a);
Result :
DATA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Example :
DECLARE @ID NVARCHAR(300)= '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20';
DECLARE @Marks NVARCHAR(300)= '0,1,2,5,8,9,4,6,7,3,5,2,7,1,9,4,0,2,5,0';
DECLARE @StudentsMark TABLE
(id NVARCHAR(300),
marks NVARCHAR(300)
);
--insert into @StudentsMark
;WITH CTE
AS (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') id,
ROW_NUMBER() OVER(ORDER BY
(
SELECT NULL
)) RN
FROM
(
SELECT CAST(''+REPLACE(@ID, ',', ' ')+' ' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a)),
CTE1
AS (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') marks,
ROW_NUMBER() OVER(ORDER BY
(
SELECT NULL
)) RN
FROM
(
SELECT CAST(''+REPLACE(@Marks, ',', ' ')+' ' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a))
INSERT INTO @StudentsMark
SELECT C.id,
C1.marks
FROM CTE C
LEFT JOIN CTE1 C1 ON C1.RN = C.RN;
SELECT *
FROM @StudentsMark;
Separate a value from string in SQL Server 2012
create the UFN_STRING_SPLIT
function suggested by @Dave here link
create FUNCTION [dbo].[UFN_STRING_SPLIT]
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(max)')
FROM
(
SELECT x = CONVERT(XML, ''
+ REPLACE(@List, @Delimiter, '')
+ '').query('.')
) AS a
CROSS APPLY x.nodes('i') AS y(i)
);
test your code:
select
Left(Item, charindex('=', Item, 0) - 1) as FielName,
right(Item, len(Item) - charindex('=', Item, 0)) as [Value]
from
dbo.UFN_STRING_SPLIT('ReferenceId=678&MobileNo=226789&Pnumber=9878&SIB=121314', '&')
How to split a string from a table SQL Server 2012?
Taking into account your link, this can be done by slightly changing the query by adding Cross Apply.
Select e.ID, t.a
From #Example As e Cross Apply (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA
FROM
(
SELECT CAST(''+REPLACE(e.List, ',', ' ')+' ' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a)) As t(a)
How to split string in SQL Server 2012?
I created a loop iterating through each set until the length of the string is reached. Then stuffed that into a stored procedure:
CREATE PROCEDURE [dbo].[SplitMyFunkyText] @Source nvarchar(MAX)
AS
DECLARE @Results AS TABLE(Part NVARCHAR(22))
DECLARE @I INT = 1
WHILE @I < LEN(@Source)
BEGIN
INSERT INTO @Results
SELECT SUBSTRING(@Source, @I, 22)
SET @I = @I + 23
END
SELECT * FROM @Results
GO
Here is a test using your example value:
DECLARE @Source AS NVARCHAR(230)
SET @Source = '123 870503-23-5370 021 456 830503-23-5371 031 789 870103-11-5372 041 654 870501-23-5373 051 321 880503-12-5374 061 987 870803-23-5375 071 109 870508-06-5376 081 174 810503-03-5377 091 509 870103-01-5378 101 687 870501-12-5379 131'
EXEC SplitMyFunkyText @Source
Here are the test results:
123 870503-23-5370 021
456 830503-23-5371 031
789 870103-11-5372 041
654 870501-23-5373 051
321 880503-12-5374 061
987 870803-23-5375 071
109 870508-06-5376 081
174 810503-03-5377 091
509 870103-01-5378 101
687 870501-12-5379 131
PER YOUR SECOND QUESTION: "how about if my splitting record are not in fixed position"
You originally indicated "fixed length" and that is much easier. For records NOT in fixed length the following will work as long as it's in groups of 3 with spaces in between:
CREATE PROCEDURE [dbo].[SplitMyFunkyText]
@Source nvarchar(MAX)
AS
DECLARE @Results AS TABLE(Part NVARCHAR(22))
DECLARE @I INT = 1
DECLARE @NextLength INT = -1
DECLARE @SubPart1 NVARCHAR(20)
DECLARE @SubPart2 NVARCHAR(20)
DECLARE @SubPart3 NVARCHAR(20)
WHILE @I < LEN(@Source)
BEGIN
-- GET 1st SubPart -----------------------------------
SET @NextLength = CHARINDEX(' ',@Source,@I)
IF @NextLength > 0
SET @SubPart1 = SUBSTRING( @Source, @I, @NextLength - @I)
ELSE
SET @SubPart1 = SUBSTRING( @Source, @I, LEN(@Source))
SET @I = @I + LEN(@SubPart1) + 1;
-- GET 2st SubPart -----------------------------------
SET @NextLength = CHARINDEX(' ',@Source,@I)
IF @NextLength > 0
SET @SubPart2 = SUBSTRING( @Source, @I, @NextLength - @I)
ELSE
SET @SubPart2 = SUBSTRING( @Source, @I, LEN(@Source))
SET @I = @I + LEN(@SubPart2) + 1;
-- GET 3st SubPart -----------------------------------
SET @NextLength = CHARINDEX(' ',@Source,@I)
IF @NextLength > 0
SET @SubPart3 = SUBSTRING( @Source, @I, @NextLength - @I)
ELSE
SET @SubPart3 = SUBSTRING( @Source, @I, LEN(@Source))
SET @I = @I + LEN(@SubPart3) + 1;
INSERT INTO @Results
SELECT @SubPart1 + ' ' + @SubPart2 + ' ' + @SubPart3
END
SELECT * FROM @Results
GO
Here is a more condensed version that works with non-fixed length fields in groups of 3:
CREATE PROCEDURE [dbo].[SplitMyFunkyText]
@Source nvarchar(MAX)
AS
DECLARE @Results AS TABLE(Part NVARCHAR(255))
DECLARE @I INT = 1
DECLARE @Start INT = 1
WHILE @I > 0
BEGIN
SET @Start = @I
SET @I = CHARINDEX(' ',@Source, 1+CHARINDEX(' ',@Source, 1+CHARINDEX(' ', @Source, @I + 1)))
IF @I > 0
INSERT INTO @Results
SELECT SUBSTRING(@Source, @Start, @I - @Start)
ELSE
INSERT INTO @Results
SELECT SUBSTRING(@Source, @Start, LEN(@Source))
END
SELECT * FROM @Results
GO
Split string in SQL server 2012 in a row
Assuming values 1-5. This can easily be done with a little XML in concert with a CROSS APPLY
If the number columns are variable, you would have to go DYNAMIC.
EDIT - Changed to nvarchar
Example
Declare @txt nvarchar(max)='2450,10,54,kb2344,kd5433;87766,500,100,ki5332108,ow092827'
Select ID=A.RetSeq
,B.*
From (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'nvarchar(max)')))
From (Select x = Cast('' + replace(@txt ,';',' ')+' ' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) A
Cross Apply (
Select Val1 = ltrim(rtrim(xDim.value('/x[1]','nvarchar(max)')))
,Val2 = ltrim(rtrim(xDim.value('/x[2]','nvarchar(max)')))
,Val3 = ltrim(rtrim(xDim.value('/x[3]','nvarchar(max)')))
,Val4 = ltrim(rtrim(xDim.value('/x[4]','nvarchar(max)')))
,Val5 = ltrim(rtrim(xDim.value('/x[5]','nvarchar(max)')))
From (Select Cast('' + replace(A.RetVal,',',' ')+' ' as xml) as xDim) as B1
) B
Returns
ID Val1 Val2 Val3 Val4 Val5
1 2450 10 54 kb2344 kd5433
2 87766 500 100 ki5332108 ow092827
Alternative of string_split Function on lower compatibility level
Here is how I have approached this in pre-string_split days, by converting the list to an XML string and then using SQL Server's XML support.
DECLARE @list varchar(255) = 'value1,value2,value3,value4,value5';
SELECT
x.f.value( '.', 'varchar(50)' ) AS [value]
FROM (
SELECT CAST ( '' + REPLACE ( @list, ',', '' ) + ' ' AS xml ) AS x
) AS d
CROSS APPLY x.nodes( '//v/i' ) x( f );
RETURNS
+--------+
| value |
+--------+
| value1 |
| value2 |
| value3 |
| value4 |
| value5 |
+--------+
You could convert this into an inline table-valued-function:
CREATE OR ALTER FUNCTION dbo.my_string_split (
@list varchar(1000), @delim varchar(1) = ','
)
RETURNS TABLE
AS
RETURN (
SELECT
x.f.value( '.', 'varchar(50)' ) AS [value]
FROM (
SELECT CAST ( '' + REPLACE ( @list, @delim, '' ) + ' ' AS xml ) AS x
) AS d
CROSS APPLY x.nodes( '//v/i' ) x( f )
)
GO
To call it:
SELECT * FROM dbo.my_string_split( 'value1,value2,value3,value4,value5', ',' );
Split a string with varying factors in SQL Server
This is tagged with [sql-server-2012]
- what a pity... With v2016+ you could call for STRING_SPLIT
or even JSON methods... The following is a rather hacky approach but works - at least with your provided test data...
Create a mockup-table (please do this yourself the next time).
DECLARE @tbl TABLE(ID INT IDENTITY, YourString VARCHAR(100));
INSERT INTO @tbl VALUES
('["2","3","4"]')
,('["1","2","3"]')
,('[]')
,('["Select option B","Select option C","Select option D"]')
,('["Moderate","Heavy","Heavy, Big & Abnormal"]');
--This is the query:
SELECT t.ID
--,t.YourString
,C.Separated.value('text()[1]','nvarchar(max)') AS Parted
FROM @tbl t
CROSS APPLY(SELECT REPLACE(REPLACE(REPLACE(YourString,'"','"'),'["',''),'"]','')) A(replaced)
CROSS APPLY(SELECT CAST('' + REPLACE((SELECT A.replaced [*] FOR XML PATH('')),'","',' ') + ' ' AS XML)) B(casted)
CROSS APPLY B.casted.nodes('/x') C(Separated);
The idea in short:
First of all I use multiple REPLACE()
to clean and harmonise your data. The second CROSS APPLY
will then use XML to split up your strings by replacing each comma together with the quotes! with XML tags. Thus we can prevent splitting at internal commas. But before, we have to use FOR XML
on the orginal string, to allow characters such as the &
in Big & Abnormal
. The rest ist rather easy XPath/XQuery
.
The result
+----+-----------------------+
| ID | Parted |
+----+-----------------------+
| 1 | 2 |
+----+-----------------------+
| 1 | 3 |
+----+-----------------------+
| 1 | 4 |
+----+-----------------------+
| 2 | 1 |
+----+-----------------------+
| 2 | 2 |
+----+-----------------------+
| 2 | 3 |
+----+-----------------------+
| 3 | [] |
+----+-----------------------+
| 4 | Select option B |
+----+-----------------------+
| 4 | Select option C |
+----+-----------------------+
| 4 | Select option D |
+----+-----------------------+
| 5 | Moderate |
+----+-----------------------+
| 5 | Heavy |
+----+-----------------------+
| 5 | Heavy, Big & Abnormal |
+----+-----------------------+
T-SQL split string
I've used this SQL before which may work for you:-
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX(',', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
END
INSERT INTO @returnList
SELECT @stringToSplit
RETURN
END
and to use it:-
SELECT * FROM dbo.splitstring('91,12,65,78,56,789')
Related Topics
Add Foreign Key Relationship Between Two Databases
SQL Server Equivalent of a Countif Aggregate Function
What Is Best Tool to Compare Two SQL Server Databases (Schema and Data)
SQL - Subtracting a Depleting Value from Rows
Dynamic Pivot Columns in SQL Server
How to Create a Step in My SQL Server Agent Job Which Will Run My Ssis Package
How to Render All Records from a Nested Set into a Real HTML Tree
T-SQL Split String Based on Delimiter
Fastest Way to Update 120 Million Records
Escaping Keyword-Like Column Names in Postgres
Using the Result of an Expression (E.G. Function Call) in a Stored Procedure Parameter List
Getting Result of Dynamic SQL into a Variable For Sql-Server
Join Two Select Statement Results
Ms Access Query: Concatenating Rows Through a Query
Delete Duplicate Rows (Don't Delete All Duplicate)
What Is Sysname Data Type in SQL Server
Accounting for Dst in Postgres, When Selecting Scheduled Items