SQL SERVER – Split Comma Separated List Without Using a Function

The best way to learn something is to revisit some of the older blogs and then look at finding a more efficient way to work on the same problem. Recently I was looking at the forums to find a question come up again and again around making a comma separated list. This is not new over this blog and if you search you will get few. Long time ago I have written below blogs to show the values stored in table as comma separate list – this is not a rehash of what was written before but a newer way to solve the problem again.

SQL SERVER – Creating Comma Separate Values List from Table – UDF – SP
SQL SERVER – Comma Separated Values (CSV) from Table Column

Recently someone asked me a reverse of that. They were storing comma separated values in a column of table. This table was getting populated from some source via SSIS package. Here is the simplified version of the problem I was presented.

DECLARE @t TABLE
(
EmployeeID INT,
Certs VARCHAR(8000)
)
INSERT @t VALUES (1,'B.E.,MCA, MCDBA, PGDCA'), (2,'M.Com.,B.Sc.'), (3,'M.Sc.,M.Tech.')

 

This is how data looks like in the table.

SQL SERVER - Split Comma Separated List Without Using a Function csv-split-01

With the above data available, they want it split into individual values. Searching for possible solutions, here is the solution query I came up with:

SELECT EmployeeID,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Certs
FROM
(
SELECT EmployeeID,CAST('<XMLRoot><RowData>' + REPLACE(Certs,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM   @t
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)


Output looks like below.

SQL SERVER - Split Comma Separated List Without Using a Function csv-split-02

Hope this would help you in your project. Let me know if you are able to find a different solution to the same problem. The best way to learn is to learn from each other.

Reference: Pinal Dave (https://blog.sqlauthority.com)

SQL Function, SQL Scripts, SQL Server
Previous Post
SQL SERVER – How to View the Dirty Pages In Memory of a Database?
Next Post
SQL SERVER – How to Identify a DB is Using Cross-Database Transactions?

Related Posts

90 Comments. Leave new

  • What about the performance?

    Reply
  • That’s a nice solution.

    I had a really badly performing split function so re-wrote it as CLR, your’s is better as it’s all SQL code.

    Reply
  • Jayshit Ladani
    April 21, 2015 2:25 pm

    This is really a unique way of doing the same thing. I really liked it.

    Reply
  • Hey, Dave,

    You still used a function:

    x.nodes(‘/XMLRoot/RowData’)m(n)

    You meant no USER function.

    Cheers!

    Reply
  • Here is another solution, no function and no XML, however I used a system table to generate rows with numbers. I don’t say is faster or nicer or easier just different. And to be honest I adapted this:

    DECLARE @t TABLE
    (
    EmployeeID INT,
    Certs VARCHAR(8000)
    )
    INSERT @t VALUES (1,’B.E.,MCA, MCDBA, PGDCA’), (2,’M.Com.,B.Sc.’), (3,’M.Sc.,M.Tech.’), (4,’Psd,,IQ’)

    SELECT
    EmployeeID,
    ltrim(rtrim(NullIf(SubString(‘,’ + Certs + ‘,’ , ID , CharIndex(‘,’ , ‘,’ + Certs + ‘,’ , ID) – ID) , ”))) AS Certs
    FROM
    (SELECT
    ID = ROW_NUMBER() OVER (ORDER BY number)
    FROM [master]..spt_values) Tally,
    @t tbl
    WHERE
    ID 0 –remove this line to keep NULL rows(or empty value; ,,)

    Reply
  • Unfortunately the code I posted was messed up by the website when submitted. Here I try again:

    DECLARE @t TABLE
    (
    EmployeeID INT,
    Certs VARCHAR(8000)
    )
    INSERT @t VALUES (1,’B.E.,MCA, MCDBA, PGDCA’), (2,’M.Com.,B.Sc.’), (3,’M.Sc.,M.Tech.’), (4,’Psd,,IQ’)

    SELECT
    EmployeeID,
    ltrim(rtrim(NullIf(SubString(‘,’ + Certs + ‘,’ , ID , CharIndex(‘,’ , ‘,’ + Certs + ‘,’ , ID) – ID) , ”))) AS Certs
    FROM
    (SELECT
    ID = ROW_NUMBER() OVER (ORDER BY number)
    FROM [master]..spt_values) Tally,
    @t tbl
    WHERE
    ID 0 –remove this line to keep NULL rows(or empty value; ,,)

    Reply
  • Ok, no chance. You cannot post code here.

    Reply
  • Hi Dave,
    I get links to your article from Toolbox.
    It is been a while that i touched any MSSQL code. I was wondering if there is an article that explains the different flavors of SQL (MS SQL, TSQL, Progue, MySQL, NoSQL, etc.) and summarizes the difference in syntax between them?
    Thank you!
    ilikecoding

    Reply
  • purposefulprocrastination
    April 22, 2015 3:52 am

    The key issue with this (and any creative use of XML capabilities) is that the source data needs to be XML escaped. A rogue less than, greater than it quote character (Unicode aside) will cause this query to fail.

    Failing at some arbitrary future point based on valid user input data is not a good thing, so I steer clear of these approaches.

    Reply
  • Pawan Kumar Khowal
    April 23, 2015 10:42 pm

    One more method —

    DECLARE @x AS XML=”
    DECLARE @Param AS VARCHAR(100) = ‘Ind,Hary,Gu’
    SET @x = CAST(‘‘+ REPLACE(@Param,’,’,’‘)+ ‘‘ AS XML)
    SELECT t.value(‘.’, ‘VARCHAR(100)’) FROM @x.nodes(‘/A’) AS x(t)

    Reply
    • There is no result from above query.

      Reply
    • Pawan Kumar Khowal
      May 6, 2015 7:04 am

      Updated–

      DECLARE @x AS XML=”
      DECLARE @Param AS VARCHAR(100) = ‘Ind,Hary,Gu’
      SET @x = CAST(”+ REPLACE(@Param,’,’,”)+ ” AS XML)
      SELECT t.value(‘.’, ‘VARCHAR(100)’) Value FROM @x.nodes(‘/r’) AS x(t)

      Output-

      Value
      ———
      Ind
      Hary
      Gu

      Reply
  • @Kumar,

    That returns nothing.

    Reply
  • Pawan Kumar Khowal
    May 6, 2015 7:20 am

    When I am commenting wordpress actually remove the XML tags from the below statement.

    SET @x = CAST(”+ REPLACE(@Param,’,’,”)+ ” AS XML)

    Here in the first single quote we have add a starting tag then & then , after adding these tags try to run the query. This is working in my environment.

    Regards,
    Pawan

    Reply
  • this thrown error like this XML parsing: line 1, character 181, semicolon expected

    Reply
  • All I have a situation where I need to split the column to rows which is delimited using commas and semicolons. Please find the below sample data.

    Data in Tables

    Test1, Test2, Test3

    Test4;Test5;Test6

    Desired output

    Test1
    Test2
    Test3
    Test4
    Test5
    Test6

    Is there any way that I can get this output in SQL other than using the XML Conversion, since the data has some special characters in this.

    Reply
  • Hi Dave, if I have both comma and “and” as the separator, what’s the best way to do it? Thanks!

    Reply
  • Thanks you so much, this sql was so helpful. :) keep up the good work!

    Reply
  • How could I join on to the your query if the result was an integer joining on to that interger
    join table p on p.Id= cert value

    Reply
  • Thank you sir. It will be great if you explain the basic of XML in separate blog because i’m not able to understand how actual XML is processed.

    Reply
  • Hi Pinal, I try to use above solution but it didn’t work for me. I am getting “XML parsing: line 1, character 55, illegal name character. Can you help me?

    Reply
  • Very nice solution! Worked great for my problem.

    Reply

Leave a Reply