2010-05-07 11 views
8

Tengo un varchar @ a = 'a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p', que tiene | valores delimitados Quiero dividir esta variable en una matriz o una tabla. ¿Alguien tiene alguna idea al respecto?¿Cómo dividir una cadena en 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-equivalent-in-tsql –

+0

posible duplicado de http://stackoverflow.com/questions/2647/split-string-in-sql –

Respuesta

11

Utilice una función con valores de tabla como esta,

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 

y conseguir que su variable y utilizar esta función como esta,

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

+1 para el delimitador que pasa ... –

+0

-1 para usar un bucle – gbn

+0

@gbn hace que la tabla de números se ejecute más rápido que un bucle ... Por favor, explique un poco más ... –

2

prueba este:

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

Buena solución, pero hay que aclarar: es importante que la cadena finalice con el símbolo del delimitador. Si no lo hace, caerá en el ciclo infinito –

+0

mi extensión a su solución es agregar esta cláusula después de su fila "set @a": IF (patindex ('% |%', @ a) = 0) COMIENZO INSERT INTO #temp select @a; \t BREAK; END; –

1

Aquí es una solución basada en XML alternativa. Parece tener un rendimiento similar al de la solución Splitfn().

Esto convierte varchar a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p en 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> y extrae el valor de cada nodo 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) 
;