2

I have nvarchar data like this:

'20030,20031,20033,20034,20065,20045,20044'

I want to read all this by spliting into array or read one by one in spliting process and do further process.

I have tried this good article but not able to do it.

3 rules
  • 1,359
  • 3
  • 26
  • 54
  • Not able how? Have you tried? Post your code and any errors? – Milney Jul 07 '17 at 13:26
  • Those who don't know the answer please don't vote it down please say in comment the mistake I have done or the person who has given answer has done if you can't please don't vote it down. thanks – 3 rules Jul 07 '17 at 13:32
  • @padhiyar : try my answer and let me know if it works – Prabhat G Jul 07 '17 at 13:34
  • @padhiyar - Read this to learn how to post questions on the site. They will be closed otherwise: https://stackoverflow.com/help/mcve – Milney Jul 07 '17 at 13:35
  • I am downvoting because this question does not show any research effort. You link one article but don't explain why you were unable to use the article to solve your problem, or why any of the other articles on the internet failed to help you. This is a very common problem, and it doesn't need another question on Stack Overflow. – Tab Alleman Jul 07 '17 at 13:40
  • @TabAlleman ok thanks – 3 rules Jul 07 '17 at 13:41

4 Answers4

5

Try this article uses function to read the comma separated values and return the table

CREATE FUNCTION dbo.Split(@String nvarchar(4000), @Delimiter char(1))
RETURNS @Results TABLE (Items nvarchar(4000))
AS
BEGIN
DECLARE @INDEX INT
DECLARE @SLICE nvarchar(4000)
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z
--     ERO FIRST TIME IN LOOP
SELECT @INDEX = 1
WHILE @INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF @INDEX !=0
SELECT @SLICE = LEFT(@STRING,@INDEX - 1)
ELSE
SELECT @SLICE = @STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO @Results(Items) VALUES(@SLICE)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
-- BREAK OUT IF WE ARE DONE
IF LEN(@STRING) = 0 BREAK
END
RETURN
END

just call the function from stored procedure or just call function like below:

SELECT items FROM [dbo].[Split] ('20030,20031,20033,20034,20065,20045,20044', ',') 
Mahavirsinh Padhiyar
  • 1,299
  • 11
  • 33
0

Not hard at all. It can be best solved using recursion

create table #Testdata2(Data varchar(max))
insert #Testdata2 select '20030,20031,20033,20034,20065,20045,20044'



;with tmp(DataItem, Data) as (
select LEFT(Data, CHARINDEX(',',Data+',')-1),
    STUFF(Data, 1, CHARINDEX(',',Data+','), '')
from #Testdata2
union all
select LEFT(Data, CHARINDEX(',',Data+',')-1),
    STUFF(Data, 1, CHARINDEX(',',Data+','), '')
from tmp
where Data > ''
)
select DataItem
from tmp
OPTION (maxrecursion 0)

output :

(select)
 Data
 ----------------
 20030,20031,20033,20034,20065,20045,20044


(query)
DataItem
----------------
20030
20031
20033
20034
20065
20045
20044
Prabhat G
  • 2,974
  • 1
  • 22
  • 31
  • @Milney :thanks for knowledge. Please share some article to prove your words ? Also if you have solution, do let us know. would love to find alternative approach – Prabhat G Jul 07 '17 at 13:37
  • 1
    Yes. Here is one: https://sqlperformance.com/2012/07/t-sql-queries/split-strings There are many if you just google t-sql split string... – Milney Jul 07 '17 at 13:38
  • 1
    Tip for the future: Recursive solutions are seldom the best way to solve a problem – Milney Jul 07 '17 at 13:40
  • Thanks. Though it doesn't say CTE are poor in performance. I have used CTE with recursion which is not terrible approach, I believe. – Prabhat G Jul 07 '17 at 13:41
  • @PrabhatG I had a split function very similar to yours, and I was pleased with it (and myself)... HOWEVER, I was amazed at the peformance of the tally approach. The following will demonstrate a tally and an xml approach https://stackoverflow.com/questions/43082763/want-a-stored-procedure-for-comma-seperated-string-which-is-of-a-column-has-200/43082930#43082930 ... Take a peek, – John Cappelletti Jul 07 '17 at 13:48
  • @PrabhatG Me too. That's why I love SO. I learn something every day. – John Cappelletti Jul 07 '17 at 13:53
  • @PrabhatG I didn't say they are 'poor' in performance per se, there is just USUALLY a much better way to do it (especially in SQL) – Milney Jul 07 '17 at 13:54
0

Another approach using String Split And Xml

DECLARE @string nvarchar(max)='20030,20031,20033,20034,20065,20045,20044'
DECLARE @Table AS TABLE (String nvarchar(max))
INSERT INTO @Table
SELECT @string

SELECT Row_NUmber ()OVER(ORDER BY (SELECT 1) )AS Seq, Split.a.value('.', 'VARCHAR(1000)') AS String
            FROM  (
                SELECT   CAST('<S>' + REPLACE(String, ',', '</S><S>') + '</S>' AS XML) AS String
                FROM @Table
                ) AS A
            CROSS APPLY String.nodes('/S') AS Split(a) 

The above code can be incorporated in function to return split string

CREATE FUNCTION dbo.udf_Split (
    @String NVARCHAR(4000)
    ,@Delimiter CHAR(1)
    )
RETURNS @Results TABLE (Items NVARCHAR(4000))
AS
BEGIN
    DECLARE @Table AS TABLE (String NVARCHAR(max))

    INSERT INTO @Table
    SELECT @String

    INSERT INTO @Results
    SELECT Split.a.value('.', 'VARCHAR(1000)') AS String
    FROM (
        SELECT CAST('<S>' + REPLACE(String, @Delimiter, '</S><S>') + '</S>' AS XML) AS String
        FROM @Table
        ) AS A
    CROSS APPLY String.nodes('/S') AS Split(a)

    RETURN
END

SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1))AS Seq,
    * FROM dbo.udf_Split('20030,20031,20033,20034,20065,20045,20044',',')

Result

Seq String
----------
1   20030
2   20031
3   20033
4   20034
5   20065
6   20045
7   20044
0

If using SQL Server 2017 or later, just use the STRING_SPLIT function.

DECLARE @numbers VARCHAR(MAX) = '7,8,9,10,11'

;WITH cte1 AS (
    SELECT [value] AS Number FROM STRING_SPLIT(@numbers, ',')
)

SELECT ROW_NUMBER() OVER (ORDER BY Number) as Id, Number
FROM cte1;

Results:

Id       Number
-------- -----------
1        7
2        8
3        9
4        10
5        11

(5 rows affected)
Greg
  • 3,861
  • 3
  • 23
  • 58