0

Can you split a database table column value of type VARCHAR into multiple values using a delimiter?

So when fetching data I would like to split values like text|another|other using pipe | as a delimiter.

We are using stored procedures and T-SQL, I have somewhat basic understanding of SQL, but my understanding is that using STRING_SPLIT https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver15 ths should be possible.

Can anyone assist me with more details?

15
  • That's correct. STRING_SPLIT would solve this by using SELECT value FROM STRING_SPLIT('text|another|other', '|'); but does only work with SQL Server 2016+ Commented Dec 13, 2019 at 16:11
  • 3
    You shouldn't store data like that in the first place. Just because there are splitting functions doesn't mean it's a good idea. It's impossible to index such fields, which means that searching for a single value requires scanning the entire table Commented Dec 13, 2019 at 16:11
  • 1
    No split function can solve this - it's a design bug, not a coding bug. If you don't care about querying on the other hand, it's probably better to split the values on the client and do whatever you want with them Commented Dec 13, 2019 at 16:12
  • 4
    Any good data architecture knows that storing delimited data in an RDBMS is a foolish idea. For starters, you have no chance of implementing foreign keys, which means you can't maintain data integrity. it's a path you don't want to go down. Commented Dec 13, 2019 at 16:14
  • 1
    @codeepic in that case clean up the data before loading it into your own database. It's far easier to split and handle values in code. For example, do you want separate columns or rows from those values? If rows, you'll have to repeat all other fields. Table rows can't be nested. When loading the data though, you can split, nest, extract the data any way you want, store it anywhere you want Commented Dec 13, 2019 at 16:19

4 Answers 4

2

It is definitely possible, and pretty straight-forward with STRING_SPLIT. Even before SQL Server 2017 when STRING_SPLIT was introduced it was possible, just not as pretty.

An example with your string would be something like this:

DECLARE @t TABLE (ID INT, StringVal VARCHAR(1000));

INSERT @t
VALUES (1, 'text|another|other');

SELECT *
FROM @t
CROSS APPLY STRING_SPLIT(StringVal, '|');

The results of this are

ID| StringVal          | value
--------------------------------
1 | text|another|other | text
1 | text|another|other | another
1 | text|another|other | other

So to answer your question, yes it is definitely possible. However, you should certainly take the comment discussion into consideration.

Sign up to request clarification or add additional context in comments.

Comments

2

Well as Panagiotis Kanavos said as a comment, the best and easiest would be to this in the 'Transform' part of your ETL (Extract, Transform, Load). When you do this, you don't even have to deal with SQL : since you are on SQL-SERVER i assume you use SSIS. You can call an external C# or .Net script to do all the work.

To answer your question, yes SQL provides a lot of builtin function to deals with string : you can use substr() + charindex(), or String_split or even write your own

Microsoft doc about String Functions : https://learn.microsoft.com/en-us/sql/t-sql/functions/string-functions-transact-sql?view=sql-server-ver15

Comments

1

The short answer is: You can do it.

The longer answer is: You shouldn't do it, because it violates the principle of Database Normalization. Anything up to NF3 is the (arguably) bare minimum, which you should stick to.

If the data enters your database from an external source, Transform it in your ETL process before it actually enters your database.

Your database should then store the data in relational form, and other transformations to fit your frontend should be done upon retrival to make it fit your consuming applications. You can read up on the ANSI-SPARC Architecture if you so desire.

1 Comment

Yes. This is screaming for an SSIS package to load the data.
1

Please check the below answer. This might help :

DECLARE @Table TABLE (ID int, SampleData Varchar(100))

INSERT @Table
(ID,SampleData)
VALUES
(1, 'text|another|other'),
(2, 'sample|data|again'),
(3, 'this|should|help')


 SELECT 
     A.ID AS ID,  
     Split.a.value('.', 'VARCHAR(100)') AS SampleData  
 FROM  (
        SELECT 
            ID,  
            CAST ('<M>' + REPLACE(SampleData, '|', '</M><M>') + '</M>' AS XML) AS SampleData  
        FROM  
            @Table A
         )  AS A 
    CROSS APPLY SampleData.nodes ('/M') AS Split(a)

The Output:-

ID  SampleData
1   text
1   another
1   other
2   sample
2   data
2   again
3   this
3   should
3   help

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.