Using SELECT statement to assign variable - sql-server

Could you explain me the strange behaviour?
DECLARE #t VARCHAR(256) = ''
SELECT #t = #t + CAST(smb.symbol AS VARCHAR(256))
FROM (
SELECT 1,'7'
UNION ALL
SELECT 2,'8'
UNION all
SELECT 3,'9'
) AS smb(n, symbol)
ORDER BY n
SELECT #t
Outputs:
789
Thats OK for me.
DECLARE #t VARCHAR(256) = ''
SELECT #t = #t + CAST(smb.symbol AS VARCHAR(256))
FROM (
SELECT NUMS.N-1 AS N, CHAR(N-1) AS symbol
FROM (
SELECT 1 + n.n1 + nn.n2 * 10 + nnn.n3 * 100 as N
FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS n(n1)
CROSS JOIN (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS nn(n2)
CROSS JOIN (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS nnn(n3)
) AS NUMS
WHERE NUMS.N BETWEEN 56 AND 58
) AS smb(N, symbol)
ORDER BY smb.N
SELECT #t
Outputs:
9
So why does the second example outputs the last symbol only?

Don't rely on order by when using mutlirows variable assignment.
try this for instance:
DECLARE #c INT = 0
SELECT
#c = #c + x
FROM (VALUES(1),(2),(3)) AS src(x)
WHERE x BETWEEN 1 AND 3
ORDER BY 1 - x DESC
SELECT #c
SET #c = 0
SELECT
#c = #c + x
FROM (VALUES(1),(2),(3)) AS src(x)
WHERE x BETWEEN 1 AND 3
ORDER BY x DESC
SELECT #c
http://sqlmag.com/sql-server/multi-row-variable-assignment-and-order

Related

Char shifting for given string

Suppose we have a varchar value like 'Durgesh' and I want to increase (Char +2) of every characters which are given in 'Durgesh'. Example:
D --> F
U --> W
R --> T
G --> I
E --> G
S --> U
H --> J
So if we put the parameter 'Durgesh', then we need the output 'Fwtiguj'.
How can I implement this with a SQL query?
This would be your function:
CREATE FUNCTION [dbo].[shifting](#Input varchar(100))
RETURNS varchar(100)
AS
BEGIN
declare
#i INT=0,
#a varchar(100) =''
while #i<LEN(#Input)
BEGIN
SET #i = #i +1
set #a = #a + char(ascii(substring(#Input,#i,1))+2)
end
RETURN #a
END
You call it as:
select [dbo].[shifting]('Durgesh') as [a]
Here is a demo
Here is a new function that will resolve the YZ and yz problem:
CREATE FUNCTION [dbo].[shifting](#Input varchar(100))
RETURNS varchar(100)
AS
BEGIN
declare
#i INT=0,
#a varchar(100) =''
while #i<LEN(#Input)
BEGIN
SET #i = #i +1
if substring(#Input,#i,1) in ('y','Y')
if ascii(substring(#Input,#i,1)) = ascii('y')
set #a = #a + 'a'
else
set #a = #a + 'A'
else
if substring(#Input,#i,1) in ('z','Z')
if ascii(substring(#Input,#i,1)) = ascii('z')
set #a = #a + 'b'
else
set #a = #a + 'B'
else
set #a = #a + char(ascii(substring(#Input,#i,1))+2)
end
RETURN #a
END
Here is a demo
Use below code :-
declare #val varchar(10) = 'Durgesh'
DECLARE #i INT = 0
WHILE #i < LEN(#val)
BEGIN
PRINT( CHAR( ASCII(SUBSTRING(#val,#i,1)) +2 ) )
SET #i = #i + 1
End
You can do this pretty easily with a tally table. I keep one on my database a view. Here is the code for my tally table. The biggest advantage a tally table has here is we don't have to do any looping!!!
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
Now that we have a tally table we can use it to make your character shift. This will work on nearly any string (until you hit the top end of the ASCII values).
declare #Val varchar(10) = 'Durgesh'
select stuff((
select char(ASCII(substring(#Val, t.N, 1)) + 2)
from cteTally t
where t.N <= len(#Val)
order by t.N
FOR XML PATH('')), 1, 0, '')
--EDIT--
Here is a new version that will "wrap" the characters back to the beginning.
declare #Val varchar(100) = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
select stuff((
select case when (ASCII(substring(#Val, t.N, 1)) > 88 AND ASCII(substring(#Val, t.N, 1)) < 91) --Upper case
OR ASCII(substring(#Val, t.N, 1)) > 120 --lower case
then char(ASCII(substring(#Val, t.N, 1)) - 24) else char(ASCII(substring(#Val, t.N, 1)) + 2) end
from cteTally t
where t.N <= len(#Val)
order by t.N
FOR XML PATH('')), 1, 0, '')

T-SQL return every other character from string

How do you return every other character from a string from a specific starting position?
Example: starting at position 1
1050231
Result:
1521
Starting at position 2
1050231
Result:
003
Using a numbers table is usually the best way to avoid loops in SQL.
If you don't already have a numbers table, you should go read Jeff Moden's The "Numbers" or "Tally" Table: What it is and how it replaces a loop.
To create a numbers table, you can use the following script:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Now that you have a numbers table, you can use it to select the specific chars from your string like this:
DECLARE #s varchar(20) = '1050231',
#Start int = 1
SELECT Substring(#s, Number, 1)
FROM Numbers
WHERE Number >= #Start
AND (Number - #Start) % 2 = 0
AND Number <= DATALENGTH(#s)
Late answer, but here's yet another option
Example
Declare #S varchar(max) = '1050231'
Declare #P int =1
Select NewValue = (Select substring(substring(#S,#P,len(#S)),N,1)
From (Select Top (len(#S)-#P+1) N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) A
Where N%2=1
For XML Path('')
)
Returns
NewValue
1521
One method uses a recursive CTE:
with cte as (
select #pos as pos, #str as str
union all
select pos + 2, str
from cte
where pos + 2 <= len(#str)
)
select substring(str, pos, 1)
from cte;
Here is a rextester.
The ugly way--a while loop, since Gordon gave the recursive CTE approach.
declare #string varchar(64) = 1050231
declare #start int = 1
declare #result varchar(64) = ''
set #result = #result + substring(#string,#start,1)
while #start < len(#string)
begin
set #start = #start + 2
select #result = #result + substring(#string,#start,1)
end
select #result
You could use STUFF:
declare #i VARCHAR(20) = '1050231';
select #i = IIF(LEN(#i) >= sub.s, STUFF(#i,sub.s,1,''),#i)
FROM(SELECT 1 s UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) sub;
-- any tally table
SELECT #i;
-- 003
declare #i VARCHAR(20) = '1050231';
select #i = IIF(LEN(#i) > sub.s, STUFF(#i,sub.s+1,1,''),#i)
FROM(SELECT 1 s UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) sub;
SELECT #i;
-- 1521
DBFiddle Demo

T-SQL: Is there a way to check if the value of one variable is present in another variable

Code:
Declare #a VARCHAR(100) = ';2;9;12;13;14;16;17;21;'
Declare #b VARCHAR(100) = ';2;12;13;'
Declare #c VARCHAR(100)
While len(#a) > 1
Begin
Set #c = substring(#a,1,charindex(';',#a,2))
Set #b += #c Where #c Not In #b ----This statement gives a problem and shows a syntax error
Set #a = substring(#a,charindex(';',#a,2),len(#a))
Select #a, #b, #c
End
What I'm trying to accomplish here is that I have declared 2 variables of VARCHAR type and assigned them some value. A third variable I've declared is a sub-string derived from the 1st variable. The value of the 3rd variable I'm trying to find it's presence in the 2nd variable and if it's not I'm trying to concatenate it with the 2nd one.
So the first value that #c would get is: ';2;' and it should compare with #b and if not present in #b it should concatenate with #b.
So basically the result should look something like this in the end.
#b = ';2;12;13;9;14;16;17;21;'
Kindly help. Thanks.
To solve your problem straightforwardly, change:
Set #b += #c Where #c Not In #b
To:
SET #b += CASE WHEN CHARINDEX(#c, #b) > 0 THEN '' ELSE #c END
If I understand your problem correctly, I believe you would want to use sets (tables) instead of strings. You could do this with strings if absolutely necessary using a split function (exists in SQL Server 2016 but will have to write your own for prior versions. There are tons of examples on S.O.)
To use sets, Try this:
DECLARE #a TABLE (id INT identity(1, 1), val INT)
DECLARE #b TABLE (Val INT)
DECLARE #c INT
DECLARE #aSetStr VARCHAR(max)
DECLARE #bSetStr VARCHAR(max)
INSERT INTO #a
VALUES (2), (9), (12), (13), (14), (16), (17), (21)
INSERT INTO #b
VALUES (2), (12), (13)
DECLARE #i INT = 0
WHILE EXISTS (
SELECT A.id
FROM #a A
LEFT JOIN #b B
ON A.Val = B.Val
WHERE A.id > #i AND B.Val IS NULL
)
BEGIN
SELECT TOP 1 #i = A.id, #c = A.Val
FROM #a A
LEFT JOIN #b B
ON A.Val = B.Val
WHERE A.id > #i AND B.Val IS NULL
ORDER BY A.id ASC
IF NOT EXISTS (
SELECT 1
FROM #b B
WHERE B.Val = #c
)
INSERT INTO #b (Val)
SELECT #c
SELECT #aSetStr = STUFF((
SELECT ';' + CAST(val AS VARCHAR(max))
FROM #a
FOR XML PATH('')
), 1, 0, '') + ';'
SELECT #bSetStr = STUFF((
SELECT ';' + CAST(val AS VARCHAR(max))
FROM #b
FOR XML PATH('')
), 1, 0, '') + ';'
SELECT #aSetStr AS [Set A], #bSetStr AS [Set B], cast(#C AS VARCHAR(255)) AS [Value of C]
END
This will Yield
Set A Set B Value of C
-------------------------- ------------------------- ------------
;2;9;12;13;14;16;17;21; ;2;12;13;9; 9
Set A Set B Value of C
-------------------------- ------------------------- ------------
;2;9;12;13;14;16;17;21; ;2;12;13;9;14; 14
Set A Set B Value of C
-------------------------- ------------------------- ------------
;2;9;12;13;14;16;17;21; ;2;12;13;9;14;16; 16
Set A Set B Value of C
-------------------------- ------------------------- ------------
;2;9;12;13;14;16;17;21; ;2;12;13;9;14;16;17; 17
Set A Set B Value of C
-------------------------- ------------------------- ------------
;2;9;12;13;14;16;17;21; ;2;12;13;9;14;16;17;21; 21
TRY THIS CODE
Declare #a VARCHAR(100) = ';2;9;12;13;14;16;17;21;'
Declare #b VARCHAR(100) = ';2;12;13;'
Declare #c VARCHAR(100)
While len(#a) > 1
Begin
Set #c = substring(#a,1,charindex(';',#a,2))
IF (#c) NOT IN (#b) begin
Set #b += #c
end
Set #a = substring(#a,charindex(';',#a,2),len(#a))
Select #a, #b, replace(#c,';','')
End
Another way of getting expected Result
Declare #a VARCHAR(100) = ';2;9;12;13;14;16;17;21;'
Declare #b VARCHAR(100) = ';2;12;13;'
DECLARE #Tempa TABLE (Value nvarchar(1000))
INSERT INTO #Tempa VALUES(#a)
DECLARE #Tempb TABLE (Value nvarchar(1000))
INSERT INTO #Tempb VALUES(#b)
;WITH cte
AS (SELECT Cast(dataa AS INT) AS DataA
FROM (SELECT split.a.value('.', 'nvarchar(1000)') AS DataA
FROM (SELECT Cast('<S>' + Replace(value, ';', '</S><S>') +
'</S>'
AS
XML) AS
Data
FROM #Tempa)AS A
CROSS apply data.nodes('S') AS Split(a)) dt
WHERE dt.dataa <> ''
UNION
SELECT Cast(dataa AS INT) AS DataA
FROM (SELECT split.a.value('.', 'nvarchar(1000)') AS DataA
FROM (SELECT Cast('<S>' + Replace(value, ';', '</S><S>') +
'</S>'
AS
XML) AS
Data
FROM #Tempb)AS A
CROSS apply data.nodes('S') AS Split(a))dt
WHERE dt.dataa <> '')
SELECT ''';' + Stuff((SELECT '; '+Cast(dataa AS VARCHAR(10)) FROM cte ORDER BY
dataa
FOR xml path ('')), 1, 1, '') + ' ;''' AS ExpectedCResult
Result
ExpectedCResult
---------------------------------
'; 2; 9; 12; 13; 14; 16; 17; 21 ;'
If your values are unique, you can use UNION to merge your strings:
Declare #a VARCHAR(100) = ';2;9;12;13;14;16;17;21;'
Declare #b VARCHAR(100) = ';2;7;12;13;'
Declare #c VARCHAR(100)
;WITH
a AS
(
SELECT #a AS FIELD, SUBSTRING(#a, 1, CHARINDEX(';', #a)) AS num
UNION ALL
SELECT RIGHT(FIELD, LEN(FIELD)-LEN(num)), SUBSTRING(RIGHT(FIELD, LEN(FIELD)-LEN(num)), 1, CHARINDEX(';', RIGHT(FIELD, LEN(FIELD)-LEN(num))))
FROM a
WHERE FIELD != num
),
b AS
(
SELECT #b AS FIELD, SUBSTRING(#b, 1, CHARINDEX(';', #b)) AS num
UNION ALL
SELECT RIGHT(FIELD, LEN(FIELD)-LEN(num)), SUBSTRING(RIGHT(FIELD, LEN(FIELD)-LEN(num)), 1, CHARINDEX(';', RIGHT(FIELD, LEN(FIELD)-LEN(num))))
FROM b
WHERE FIELD != num
)
SELECT #c =
(
SELECT ';' + CAST(v.num AS VARCHAR)
FROM (
SELECT CAST(REPLACE(a.num, ';', '') AS INT) num
FROM a
WHERE a.num != ';'
UNION
SELECT CAST(REPLACE(b.num, ';', '') AS INT)
FROM b
WHERE b.num != ';'
) v
FOR XML PATH('')
) + ';'
SELECT #c

How to get all the single number from [number -(to) number] with comma-seperated in a column in sql server

column of data in sqlserver like
numbers
1000-1050, 1054, 1090-1230, 1245
numbers
-------
1000-1050, 1054, 1090-1230, 1245
how to get the style like below:
numbers
-------
1000
1001
1002
1003
1004
...
1050
1054
1090
1091
1092
...
1245
You could use a split function and APPLY like this
DECLARE #SampleData AS TABLE
(
numbers varchar(200)
)
INSERT INTO #SampleData
VALUES ('1000-1050, 1054, 1090-1230, 1245')
;WITH temp AS
(
SELECT 1 AS Number
UNION ALL
SELECT t.Number + 1 FROM temp t
WHERE t.Number < 5000
) -- return table from 1 --> 5000
SELECT DISTINCT
ca2.*
FROM #SampleData sd
CROSS APPLY
(
SELECT pos, LTRIM(Value) AS Value
FROM dbo.SplitString(sd.Numbers,',')
) ca1
CROSS APPLY
(
SELECT *
FROM temp t WHERE t.Number BETWEEN LEFT(ca1.[Value], charindex('-', ca1.[Value] + '-') - 1) AND
CASE
WHEN len(ca1.[Value]) < charindex('-', ca1.[Value] + '-') THEN ca1.[Value]
ELSE RIGHT(ca1.[Value], len(ca1.[Value]) - charindex('-', ca1.[Value] + '-'))
END
) ca2
OPTION (MAXRECURSION 0)
Split function
CREATE FUNCTION [dbo].[SplitString] (#Text varchar(max),#Delimiter varchar(10))
Returns Table
As
Return (
Select Pos = Row_Number() over (Order By (Select null))
,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(#Text,#Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
Demo link: http://rextester.com/GIPGR78132
First split the comma seperated values, then get the values using a recursive common table expression.
Declare #values nvarchar(max) = '1000-1050, 1054, 1090-1230, 1245'
;with ranges_cte as
(
select cast(case pos when 0 then ResultValue else left(ResultValue,pos-1) end as int) first, cast(case pos when 0 then ResultValue else substring(ResultValue,pos+1,len(ResultValue)-pos) end as int) Last
from (
select ResultValue, charINDEx('-',ResultValue) pos
from dbo.SplitString(#values,',')) x
)
, values_rte as
(
select first,last,first as active
from ranges_cte
union all
select first,last,active +1 as active
from values_rte
where active< last
)
select *
from values_rte
OPTION (MAXRECURSION 0)
Function to split the values:
Create FUNCTION [dbo].[SplitString] (#StringArray NVARCHAR(MAX), #Delimiter NVARCHAR(10))
RETURNS #ResultedValues table
(
nr int,
ResultValue nvarchar(max)
)
AS
--select * from dbo.splitstring ('123,456,789',',')
BEGIN
declare #string nvarchar(max)
declare #nr int = 1
set #string = #StringArray
WHILE (CHARINDEX(#Delimiter,#String)>0)
BEGIN
INSERT INTO #ResultedValues (nr,ResultValue) VALUES (#nr,LTRIM(RTRIM(SUBSTRING(#String,1,CHARINDEX(#Delimiter,#String)-1))))
SET #String = SUBSTRING(#String, CHARINDEX(#Delimiter,#String)+LEN(#Delimiter),LEN(#String))
set #nr = #nr +1
END
INSERT INTO #ResultedValues (nr,ResultValue ) VALUES ( #nr, LTRIM(RTRIM(#String)))
RETURN
END
Create a split function:
CREATE FUNCTION [dbo].[SplitIDsTest]
(
#idList varchar(4000)
)
RETURNS #parsedList TABLE
(
Id varchar(50),
Nr int
)
AS
BEGIN
DECLARE #id varchar(10), #pos int
DECLARE #nr int = 0;
SET #idList = LTRIM(RTRIM(#idList)) + ','
SET #Pos = CHARINDEX(',', #idList)
IF REPLACE(#idList, ',', '') <> ''
BEGIN
WHILE #Pos > 0
BEGIN
SET #id = LTRIM(RTRIM(LEFT(#idList, #pos - 1)))
IF #id <> ''
BEGIN
set #nr += 1;
INSERT INTO #ParsedList (Id, Nr)
VALUES (#id, #nr);
END
SET #idList = RIGHT(#idList, LEN(#idList) - #pos) -- 'WMPC,' (inklusive Komma) links vom Eingabeparameter abschneiden, weil jetzt der nächste Wert gesucht wird
SET #pos = CHARINDEX(',', #idList, 1) -- Nächste Position eines Kommas suchen und in der WHILE-Schleife weitermachen
END
END
RETURN
END
Then a tally table:
select top 1000000 N=identity(int, 1, 1)
into dbo.Tally
from master.dbo.syscolumns a cross join master.dbo.syscolumns b;
Then use:
select distinct Tally.N
from SplitIDsTest('10-12, 34, 9') splitted
join Tally on 1 = case
when CHARINDEX('-', splitted.Id) > 0 then
case
when Tally.N between cast(left(splitted.Id, CHARINDEX('-', splitted.Id) - 1) as int)
and cast(right(splitted.Id, len(splitted.Id) - CHARINDEX('-', splitted.Id)) as int) then 1
else 0
end
when Tally.N = cast(splitted.Id as int) then 1
else 0
end
order by Tally.N

comma separated string using CTE

I have a string '1,2,3,4,5,6,', i want the result in array like :
1
2
3
4
5
I have tried it using function and also done by convertingit to the xml.
I have a query:
with cte1 (str1,str2) AS
(
SELECT SUBSTRING('1,2,3,4,5,6,',1,1) X,
SUBSTRING('1,2,3,4,5,6,',CHARINDEX(',','1,2,3,4,5,6,,') +1,LEN('1,2,3,4,5,6,')-2) Y
UNION all
SELECT SUBSTRING(str2,1,1) X ,SUBSTRING(str2,CHARINDEX(',',str2)+1,LEN(str2)-2) Y
FROM CTE1
WHERE SUBSTRING(str2,CHARINDEX(',',str2)+0,1) <> ' ' )
SELECT str1 FROM CTE1;
which gives the result as expected.
but if i am changing the string it gives random reults like :
with cte1 (str1,str2) AS
(
SELECT SUBSTRING('24,78,45,56,',1,1) X,
SUBSTRING('24,78,45,56,',CHARINDEX(',','24,78,45,56,') +1,LEN('24,78,45,56,')-2) Y
UNION all
SELECT SUBSTRING(str2,1,1) X ,SUBSTRING(str2,CHARINDEX(',',str2)+1,LEN(str2)-2) Y
FROM CTE1
WHERE SUBSTRING(str2,CHARINDEX(',',str2)+0,1) <> ' ' )
SELECT str1 FROM CTE1;
result :
2
7
4
5
This will work only when string is like '12,34,45,56....'i.e string contains two digit comm separated values
with cte1 (str1,str2) AS
(
SELECT SUBSTRING('24,78,45,56,',1,2) X,
SUBSTRING('24,78,45,56,',CHARINDEX(',','24,78,45,56,') +1,LEN('24,78,45,56,')-2) Y
UNION all
SELECT SUBSTRING(str2,1,2) X ,SUBSTRING(str2,CHARINDEX(',',str2)+1,LEN(str2)-2) Y
FROM CTE1
WHERE SUBSTRING(str2,CHARINDEX(',',str2)+0,2) <> ' ' )
SELECT str1 FROM CTE1;
You should go with generic solution by creating on user define function which accepts comma separated string and give table value for this string
Function definition like this
CREATE FUNCTION SplitItem( #ItemIDs VARCHAR(MAX))
RETURNS #ItemTable TABLE ( Item VARCHAR(200) )
AS
BEGIN
DECLARE #Item VARCHAR(200)
DECLARE #Index INT
WHILE LEN(#ItemIDs) <> 0
BEGIN
SET #Index = PATINDEX('%,%', #ItemIDs)
IF #Index > 0
BEGIN
SET #Item = SUBSTRING(#ItemIDs, 1, #Index - 1)
SET #ItemIDs = RIGHT(#ItemIDs, LEN(#ItemIDs) - #Index)
INSERT INTO #ItemTable
VALUES ( #Item )
END
ELSE
BEGIN
BREAK
END
END
SET #Item = #ItemIDs
INSERT INTO #ItemTable
VALUES ( #Item )
RETURN
END
And Use this function like this
SELECT Item
FROM SplitItem('1,2,3,44,55,66,77')
This will gives output like this
1
2
3
44
55
66
77
You could use a recursive CTE
Declare #list NVARCHAR(MAX) = '1,2,3,4,5'
DECLARE #length INT = LEN(#list) + 1;
WITH a AS
(
SELECT
[start] = 1,
[end] = COALESCE(NULLIF(CHARINDEX(',',
#List, 1), 0), #length),
[value] = SUBSTRING(#list, 1,
COALESCE(NULLIF(CHARINDEX(',',
#List, 1), 0), #length) - 1)
UNION ALL
SELECT
[start] = CONVERT(INT, [end]) + 1,
[end] = COALESCE(NULLIF(CHARINDEX(',',
#list, [end] + 1), 0), #length),
[value] = SUBSTRING(#list, [end] + 1,
COALESCE(NULLIF(CHARINDEX(',',
#list, [end] + 1), 0), #length)-[end]-1)
FROM a
WHERE [end] < #length
)
SELECT [value]
FROM a
WHERE LEN([value]) > 0
OPTION (MAXRECURSION 0);
You can do something like this:
DECLARE #string NVARCHAR(MAX) = '1,2,3,4,5,6,',
#xml xml
select #xml = cast('<d><q>'+REPLACE(#string,',','</q><q>')+'</q></d>' as xml)
SELECT n.v.value('.','nvarchar(2)')
FROM #xml.nodes('/d/q') AS n(v);
The result:
----
1
2
3
4
5
6
(7 row(s) affected)

Resources