2010-05-07 2 views
8

У меня есть varchar @ a = 'a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p', которые имеют | разграниченные значения. Я хочу разбить эту переменную в массиве или таблице. У кого-нибудь есть представление об этом.Как разбить строку в T-SQL?

+1

http://stackoverflow.com/questions/314824/t-sql-opposite-to-string-concatenation-how-to-split-string-into-multiple-recor, HTTP: // StackOverflow. com/questions/697519/split-function -equit-in-tsql –

+0

Возможный дубликат http://stackoverflow.com/questions/2647/split-string-in-sql –

ответ

11

Используйте таблицу значных функции, как это,

CREATE FUNCTION Splitfn(@String varchar(8000), @Delimiter char(1))  
returns @temptable TABLE (items varchar(8000))  
as  
begin  
    declare @idx int  
    declare @slice varchar(8000)  

    select @idx = 1  
     if len(@String)<1 or @String is null return  

    while @idx!= 0  
    begin  
     set @idx = charindex(@Delimiter,@String)  
     if @idx!=0  
      set @slice = left(@String,@idx - 1)  
     else  
      set @slice = @String  

     if(len(@slice)>0) 
      insert into @temptable(Items) values(@slice)  

     set @String = right(@String,len(@String) - @idx)  
     if len(@String) = 0 break  
    end 
return  

end 

и получить переменную и использовать эту функцию, как это,

SELECT i.items FROM dbo.Splitfn(@a,'|') AS i 
+0

+1 для прохода разметки ... – 2010-05-07 05:29:31

+0

-1 для использования цикла – gbn

+0

@gbn таблица чисел выполняется быстрее, чем цикл .... Пожалуйста, объясните немного больше ... –

2

В общем, это такой общий вопрос здесь

Я дам общий ответ: Arrays and Lists in SQL Server 2005 and Beyond от Erland Sommarskog

Я бы рекомендовал table of numbers, а не цикл, для общего использования.

+0

Возможно, вы могли бы улучшить answe r, объясняя, как применить этот метод для разбиения текста на каждом разделителе. =) – jumxozizi

2

Попробуйте это:

declare @a varchar(10) 
set @a = 'a|b|c|' 
while len(@a) > 1 
begin 
insert into #temp 
select substring(@a,1,patindex('%|%',@a)-1); 
set @a = substring(@a,patindex('%|%',@a)+1,len(@a)) 
end; 
+0

Хорошее решение, но нужно уточнить - важно, чтобы строка заканчивалась символом-разделителем. Если это не произойдет - вы попадете в бесконечный цикл –

+0

мое расширение к вашему решению должно добавить это предложение после строки «set @a»: IF (patindex ('% |%', @ a) = 0) BEGIN INSERT INTO #temp select @a; \t BREAK; END; –

1

Вот решение, основанное альтернатива XML. Похоже, что он имеет такую ​​же производительность, как и решение Splitfn().

Это преобразует varchar a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p в XML <a>a</a><a>b</a><a>c</a><a>d</a><a>e</a><a>f</a><a>g</a><a>h</a><a>i</a><a>j</a><a>k</a><a>l</a><a>m</a><a>n</a><a>o</a><a>p</a> и извлекает значение из каждого узла XML <a>.

declare @a  varchar(max); 
set @a = 'a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p'; 

declare @xml xml; 
set @xml  
    = '<a>'+replace(replace(replace(@a,'&','&amp;'),'<','&lt;'),'|','</a><a>')+'</a>'; 

SELECT x.n.value('.','VARCHAR(1)') AS singleValue 
FROM @xml.nodes('/a') AS x(n) 
; 
Смежные вопросы