Skip to content

STRING_SPLIT String Function

The STRING_SPLIT string function is a table-valued function that splits a string into rows of substrings, based on a specified separator character.

Compatibility level 130

STRING_SPLIT requires the compatibility level to be at least 130. When the level is less than 130, the Database Engine is unable to find the STRING_SPLIT function.

SELECT compatibility_level
FROM sys.databases WHERE name = 'SQLServerHelper';
compatibility_level
110
SELECT * FROM STRING_SPLIT('A,B,C', ',');
Query 1 ERROR at Line 22: : Msg: 208, Line 1, State: 1, Level: 16
Invalid object name 'STRING_SPLIT'.

Syntax

STRING_SPLIT ( string , separator [ , enable_ordinal ] )

Arguments

string

An expression of any character type (for example, nvarchar, varchar, nchar, or char).

separator

A single character expression of any character type (for example, nvarchar(1), varchar(1), nchar(1), or char(1)) that is used as separator for concatenated substrings.

enable_ordinal

An int or bit expression that serves as a flag to enable or disable the ordinal output column. A value of 1 enables the ordinal column. If enable_ordinal is omitted, NULL, or has a value of 0, the ordinal column is disabled.

Note: This option is only available to Azure SQL Database, Azure SQL Managed Instance, Azure Synapse Analytics (serverless SQL pool only), and SQL Server 2022 (16.x) and later versions

Return Types

If the ordinal output column isn't enabled, STRING_SPLIT returns a single-column table whose rows are the substrings. The name of the column is value. It returns nvarchar if any of the input arguments are either nvarchar or nchar. Otherwise, it returns varchar. The length of the return type is the same as the length of the string argument.

If the enable_ordinal argument is passed a value of 1, a second column named ordinal is returned that consists of the 1-based index values of each substring's position in the input string. The return type is bigint.

Sample Uses of the STRING_SPLIT String Function

Here are sample uses of the STRING_SPLIT string function

Usage #1 : Transpose a Table

WITH NBAChampions AS (
    SELECT *
    FROM (VALUES ('Boston Celtics', '2008,2024'),
                 ('Cleveland Cavaliers', '2016'),
                 ('Dallas Mavericks', '2011'),
                 ('Denver Nuggets', '2023'),
                 ('Detroit Pistons', '2004'),
                 ('Golden State Warriors', '2015,2017,2018,2022'),
                 ('Los Angeles Lakers', '2000,2001,2002,2009,2010,2020'),
                 ('Miami Heat', '2006,2012,2013'),
                 ('Milwaukee Bucks', '2021'),
                 ('San Antonio Spurs', '2003,2005,2007,2014'),
                 ('Toronto Raptors', '2019'))
    AS [NBATeams] ( [TeamName], [YearsWon])
)
SELECT [value] AS [Year], [TeamName]
FROM NBAChampions CROSS APPLY STRING_SPLIT([YearsWon], ',')
ORDER BY [value];
Year TeamName
2000 Los Angeles Lakers
2001 Los Angeles Lakers
2002 Los Angeles Lakers
2003 San Antonio Spurs
2004 Detroit Pistons
2005 San Antonio Spurs
2006 Miami Heat
2007 San Antonio Spurs
2008 Boston Celtics
2009 Los Angeles Lakers
2010 Los Angeles Lakers
2011 Dallas Mavericks
2012 Miami Heat
2013 Miami Heat
2014 San Antonio Spurs
2015 Golden State Warriors
2016 Cleveland Cavaliers
2017 Golden State Warriors
2018 Golden State Warriors
2019 Toronto Raptors
2020 Los Angeles Lakers
2021 Milwaukee Bucks
2022 Golden State Warriors
2023 Denver Nuggets
2024 Boston Celtics

Usage #2 : Sort a Comma-Delimited List of IPv4 Addresses

DECLARE @Input VARCHAR(1000)
DECLARE @Output VARCHAR(1000)

SET @Input = '10.0.0.1,192.120.40.243,207.46.199.60,255.255.0.0,255.255.255.255,64.233.188.15,98.123.251.21';

SELECT TOP 100 @Output = ISNULL(@Output + ',' + value, value)
FROM STRING_SPLIT(@Input, ',')
ORDER BY CAST(PARSENAME([value], 4) AS INT),
         CAST(PARSENAME([value], 3) AS INT),
         CAST(PARSENAME([value], 2) AS INT),
         CAST(PARSENAME([value], 1) AS INT);

SELECT @Output AS [Output]
Output
10.0.0.1,64.233.188.15,98.123.251.21,192.120.40.243,207.46.199.60,255.255.0.0,255.255.255.255

Take note of the TOP 100 clause in the query. Theoretically, that clause is not needed to generate the desired output but somehow it seems that there is bug with the STRING_SPLIT string function when the value column is assigned to a variable (in this case, the @Output variable) and the query includes an ORDER BY clause wherein the expression used is not just the value column by itself but an expression that uses operators.

Using the same query above but not include the TOP 100 clause:

DECLARE @Input VARCHAR(1000)
DECLARE @Output VARCHAR(1000)

SET @Input = '10.0.0.1,192.120.40.243,207.46.199.60,255.255.0.0,255.255.255.255,64.233.188.15,98.123.251.21';

SELECT @Output = ISNULL(@Output + ',' + value, value)
FROM STRING_SPLIT(@Input, ',')
ORDER BY CAST(PARSENAME([value], 4) AS INT),
         CAST(PARSENAME([value], 3) AS INT),
         CAST(PARSENAME([value], 2) AS INT),
         CAST(PARSENAME([value], 1) AS INT);

SELECT @Output AS [Output];

The output of the query is as follows:

Output
255.255.255.255

Usage #3 : Sort a Comma-Delimited String

DECLARE @Input VARCHAR(1000)
DECLARE @Output VARCHAR(1000)

SET @Input = 'one,two,three,four,five,six,seven,eight,nine,ten'

SELECT @Output = ISNULL(@Output + ',' + value, value)
FROM STRING_SPLIT(@Input, ',')
ORDER BY value;

SELECT @Output AS [Output];
Output
eight,five,four,nine,one,seven,six,ten,three,two

Usage #4 : Create a Integer Table

WITH Digits AS (
    SELECT CAST(value AS TINYINT) AS value
    FROM STRING_SPLIT('0,1,2,3,4,5,6,7,8,9', ',')
)
SELECT (tens.value * 10) + ones.value AS Number
FROM Digits tens CROSS JOIN Digits ones
ORDER BY Number;
Number
0
1
2
3
4
5
6
...
95
96
97
98
99

Usage #5 : Parse a Query String

DECLARE @QueryString   VARCHAR(100)
SET @QueryString = 'street=1600+Pennsylvania+Avenue+NW&city=Washington&state=DC&zip=20500'
SELECT LEFT(value, CHARINDEX('=', value) - 1) AS [Key],
       RIGHT(value, CHARINDEX('=', REVERSE(value)) - 1) AS [Value]
FROM STRING_SPLIT(@QueryString, '&');
Key Value
street 1600+Pennsylvania+Avenue+NW
city Washington
state DC
zip 20500

Usage #6 : Create a Multiplication Table

WITH Digits AS (
    SELECT CAST(value AS TINYINT) AS value
    FROM STRING_SPLIT('1,2,3,4,5', ',')
)
SELECT CONCAT(d1.value, ' * ', d2.value, ' = ', d1.value * d2.value) AS MultiplicationTable
FROM Digits d1 CROSS JOIN Digits d2;
MultiplicationTable
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25