Как уже упоминал Алон, вам нужна функция или запрос, чтобы разбить значения на строки в таблице. Другой способ сделать это - с помощью таблицы Numbers, которая может быть статической или созданной как часть общего выражения таблицы:
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
Здесь разделитель пространства представляет небольшую проблему. Функция Len
игнорирует пробелы при определении, поэтому я использовал функцию DataLength
, а также гарантировал, что @Delimiter
был объявлен как varchar
вместо nvarchar
. DataLength
вернет количество байтов в строке, которое будет вдвое больше общего количества символов для nvarchar
.
Числа CTE (или это может быть статическая таблица) - это просто статический список последовательных целых чисел, который весьма полезен для ситуаций, подобных этой.
Подход такого типа также может быть включен в общий запрос, где вы анализируете каждую строку в другой таблице, например:
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