в продолжение темы http://www.community.terrasoft.ru/blogs/10000
версия 2
Чтобы в MSSQL из строки получить набор строк (например, для использования в качестве параметра для select ... where ... in (***)), предлагаю следующее:
declare @input_str nvarchar(4000) = '' -- входная строка
declare @IncludedTablesStringTable TABLE (Code uniqueidentifier) -- смени тип
declare @IncludedTablesStringCode nvarchar(4000)
declare @delimeter nvarchar(4000) = ', '
declare @pos int = 0
declare @len int = LEN(@input_str + cast(2 AS varchar)) - 1
declare @lend int = LEN(@delimeter + cast(2 AS varchar)) - 1
declare @oldpos int = 0
declare @substr nvarchar(4000)
while (@pos = @len)
begin
SET @substr = SUBSTRING(@input_str, @pos, @lend)
IF (@substr = @delimeter OR @pos = @len)
begin
SET @substr = SUBSTRING(@input_str, @oldpos,
@pos - @oldpos + case when (@pos = @len) then 1 else 0 end
)
INSERT INTO @IncludedTablesStringTable (Code) VALUES (@substr)
SET @pos = @pos + @lend
SET @oldpos = @pos
continue
end
SET @pos = @pos + 1
end
(SELECT Code FROM @IncludedTablesStringTable)
Комментарии:
- для использования вставляете (select Code from @IncludedTablesStringTable) туда, где нужен набор строк
- почему все строки nvarchar(4000)? Меня учили, что программа должна работать как можно в большей вариантивности входящих значений. А так как ничто не мешает использовать какую-то странную кодировку или какой-то гигантский разделитель, из ограничений на переменные поставил только юникод.
- что это?
declare @len int = LEN(@input_str + cast(2 AS varchar)) - 1
declare @lend int = LEN(@delimeter + cast(2 AS varchar)) - 1
дело в том, что нам нужен размер разделителя и строки, но LEN() обрезает пробелы в конце (из-за этого я потратил на часок больше времени
). Поэтому идем на хитрость: добавляем знак в конце, считаем, отнимаем единицу. Ну а CAST() используется т.к. если вставлять код со строками в exec(), то начинаются сложности всякие, а так - мы обходим эту проблему. Конечно, можно использовать и другие решения для учета конечных пробелов, но все, что придумал, показались не надежными
- скрипт начинает путаться если разделители идут подряд (не разделены смыслом ), т.е. при разделителе ',' строка '12345,6789,321,,,' распарсится в
- и последнее, в declare @IncludedTablesStringTable не забудьте указать тип данных тот, который вам нужен