The STRING_SPLIT function in SQL Server
Syntax:
The syntax is very simple as this table valued built-in function takes
only two parameters. First one is a string and the second one is a
single character.
STRING_SPLIT (string, separator)
The following sample shows simplest usage of this function.
select value from STRING_SPLIT('apple,banana,lemon,kiwi,orange,coconut',',') |
The following SELECT query will return an error because of the database compatibility level.
ALTER DATABASE AdventureWorks2012 SET compatibility_LEVEL=120 GO select value from STRING_SPLIT('apple , banana , lemon , kiwi , orange ,coconut',',') |
The reason for this error is that we decreased the database
compatibility level under the 130 and SQL Server returns an error. Keep
in mind, that if you are planning to use this function in your customer
environment you have to be sure about their database compatibility
level.
STRING_SPLIT and WHERE clause:
Through the WHERE clause, we can filter the result set of the
STRING_SPLIT function. In the following select statement, the WHERE
clause will filter the result set of the function and will only return
the row or rows which start with “le”
select value from STRING_SPLIT('apple,banana,lemon,kiwi,orange,coconut',',') WHERE value LIKE 'le%' |
Also, we can use the function in this form:
USE AdventureWorks2014 GO select * from HumanResources.Employee WHERE [jobtitle] IN (select value from string_split('Chief Executive Officer , Design Engineer',',')) |
Now, we will look at the execution plan with help of ApexSQL Plan. We can see the Table valued function operator in the execution plan.
When we hover over the table-valued function operator in the execution
plan, we can find out all the details about this operator. Under the
object label, the STRING_SPLIT function can be seen. These all details
tell us that this function is a table-valued function.
STRING_SPLIT and ORDER BY
Another requirement which we need in the SELECT statements is sorting
functionality. We can sort the output of this function which looks like
the other T-SQL statements.
select value from STRING_SPLIT('apple,banana,lemon,kiwi,orange,coconut',',') order by value |
Note: When I reviewed some customer feedback about SQL Server, I came across a suggestion
about the STRING_SPLIT function which is “The new string splitter
function in SQL Server 2016 is a good addition but it needs an extra
column, a ListOrder column which denotes the order of the split values.”
In my thought, this feature can be very useful for this function and I
voted for this suggestion.
STRING_SPLIT and JOIN:
We can combine the function result set to the other table with the JOIN clause.
USE [AdventureWorks2014] GO SELECT [PersonType] ,[NameStyle] ,[FirstName] ,[MiddleName] ,[LastName] FROM [Person].[Person] P INNER JOIN string_split('Ken,Terri,Gail',',') on P.FirstName=value |
Also, we can use CROSS APPLY function to combine the STRING_SPLIT
function result set with other tables. CROSS APPLY function provides us
to join table value function output to other tables.
In the following sample, we will create two tables and first table
(#Countries) stores name and the continent of countries and second table
(#CityList) stores city of countries table but the crucial point is
#CityList table stores the city names as a string array which is
separated by a comma. We will join this to the table over country
columns and use the CROSS APPLY function to transform city array into a
column. The below image can illustrate what will we do.
DROP TABLE IF EXISTS #Countries GO DROP TABLE IF EXISTS #CityList GO CREATE TABLE #Countries (Continent VARCHAR(100), Country VARCHAR(100)) GO CREATE TABLE #CityList (Country VARCHAR(100), City VARCHAR(5000)) GO INSERT INTO #Countries VALUES('Europe','France'),('Europe','Germany') INSERT INTO #CityList VALUES('France','Paris,Marsilya,Lyon,Lille,Nice'), ('Germany','Berlin,Hamburg,Munih,Frankfurt,Koln') SELECT CN.Continent,CN.Country,value FROM #CityList CL CROSS APPLY string_split(CL.City,',') INNER JOIN #Countries CN ON CL.Country = CN.Country DROP TABLE IF EXISTS #Countries GO DROP TABLE IF EXISTS #CityList GO |
More details about STRING_SPLIT
After all the basic usage methodology of this function; we will delve
into more detail. In the previous examples we always used a comma (,)
as a separator for the function, however, we may need to use other
symbols as a separator. The STRING_SPLIT function allows us to use other
symbols as a separator, but it has one limitation about this usage.
According to the MSDN; separator is a single data type and this
parameter data types can be nvarchar (1), char (1), and varchar (1).
Now, we will make a sample about it. The following SELECT statement will
run without error. As well as we will use at (@) instead of a comma
(,).
DECLARE @STRINGLIST AS VARCHAR(1000)='apple,banana,lemon,kiwi,orange,coconut' DECLARE @SEPERATOR VARCHAR(1)=',' select * from STRING_SPLIT(@STRINGLIST,@SEPERATOR) |
However, the following SELECT statement will return an error because of the data type declaration.
DECLARE @STRINGLIST AS VARCHAR(1000)='apple@+@banana@+@lemon@+@kiwi@+@orange@+@coconut' DECLARE @SEPERATOR VARCHAR(3)='@+@' select * from STRING_SPLIT(@STRINGLIST,@SEPERATOR) |
“Procedure expects parameter ‘separator’ of type
‘nchar(1)/nvarchar(1)’”. The definition of error is very clear and it
indicates a problem that is related to the data type of separator. After
this sample, a question can appear in your mind. Can we assign NULL
value to separator? We will test and learn.
DECLARE @STRINGLIST AS VARCHAR(1000)='apple,banana,lemon,kiwi,orange,coconut' DECLARE @SEPERATOR VARCHAR(1)=NULL select * from STRING_SPLIT(@STRINGLIST,@SEPERATOR) |
We cannot assign NULL value to separator as a value.
In addition, when we use this function for numerical values, the
result set will be in string data types. When we execute the following
query, we can see all details and result in set table data type.
DROP TABLE IF EXISTS TempStringSplit SELECT VALUE INTO TempStringSplit FROM string_split('1,2,3',',') AS StrSplit SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='TempStringSplit' DROP TABLE IF EXISTS TempStringSplit |
Now we will analyze the following query execution plan with ApexSQL Plan.
DROP TABLE IF EXISTS TempNumerical GO CREATE TABLE TempNumerical (NumberId INT) INSERT INTO Numerical VALUES ( 1),(2),(3),(5) GO SELECT * FROM Numerical INNER JOIN string_split('1,2,3',',') AS StrSplit ON Numerical.NumberId = StrSplit.value |
In the select operator, you are seeing a warning sign and now find out the details about this warning.
The reason for this warning is that we tried to join integer data type
to varchar data type, so this type of usage causes implicit conversion.
Implicit conversions affect the performance query.