As Alon mentioned, you need a function or query to split the values into rows in a table. Another way to do this is with a Numbers table which can be static or created as part of a common table expression:
Declare @Alist varchar(50);
Declare @Delimiter char(1);
Declare @DelimiterLength int;
Set @Delimiter = ' ';
Set @DelimiterLength = DataLength(@Delimiter);
Set @Alist = 'A1 A2 A3';
Set @Alist = @Delimiter + @Alist + @Delimiter;
With Numbers As
(
Select Row_Number() Over ( Order By C1.object_id ) As Value
From sys.columns As C1
Cross Join sys.columns As C2
)
Select CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength As Position
, Substring (
@Alist
, CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength
, CharIndex(@Delimiter, @Alist, N.Value + 1)
- ( CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength )
) As Value
From Numbers As N
Where N.Value Between 1 And ( Len(@Alist) - 1 )
And Substring(@Alist, N.Value, @DelimiterLength) = @Delimiter
Order By N.Value
Here the space delimiter presents a small problem. The Len
function ignores spaces in its determination so I used the DataLength
function and also ensure that @Delimiter
was declared as a varchar
instead of a nvarchar
. DataLength
will return the number of bytes in the string which will be twice the number of characters in general for a nvarchar
.
The Numbers CTE (or it could be a static table) is just a static list of sequential integers which is quite useful for situations just like this one.
This type of approach can also be incorporated into a general query where you analyze every row in another table like so:
With Numbers As
(
Select Row_Number() Over ( Order By C1.object_id ) As Value
From sys.columns As C1
Cross Join sys.columns As C2
)
Select CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength
, Substring (
A.List
, CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength
, CharIndex(@Delimiter, A.List, N.Value + 1)
- ( CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength )
)
From Numbers As N
Cross Join ( Select A1.List From SomeTable ) As A
Where N.Value Between 1 And ( Len(A.List) - 1 )
And Substring(A.List, N.Value, @DelimiterLength) = @Delimiter
Order By N.Value