¿Función dividida equivalente en T-SQL?

Resuelto jinsungy asked hace 15 años • 16 respuestas

Estoy buscando dividir '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15...' (delimitado por comas) en una tabla o variable de tabla .

¿Alguien tiene una función que devuelva cada uno seguido?

jinsungy avatar Mar 30 '09 21:03 jinsungy
Aceptado

Prueba esto

DECLARE @xml xml, @str varchar(100), @delimiter varchar(10)
SET @str = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'
SET @delimiter = ','
SET @xml = cast(('<X>'+replace(@str, @delimiter, '</X><X>')+'</X>') as xml)
SELECT C.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as X(C)

O

DECLARE @str varchar(100), @delimiter varchar(10)
SET @str = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'
SET @delimiter = ','
;WITH cte AS
(
    SELECT 0 a, 1 b
    UNION ALL
    SELECT b, CHARINDEX(@delimiter, @str, b) + LEN(@delimiter)
    FROM CTE
    WHERE b > a
)
SELECT SUBSTRING(@str, a,
CASE WHEN b > LEN(@delimiter) 
    THEN b - a - LEN(@delimiter) 
    ELSE LEN(@str) - a + 1 END) value      
FROM cte WHERE a > 0

Aquí hay muchas más formas de hacer lo mismo. ¿Cómo dividir una cadena delimitada por comas?

priyanka.sarkar avatar Dec 04 '2009 12:12 priyanka.sarkar

Aquí hay una solución algo anticuada:

/*
    Splits string into parts delimitered with specified character.
*/
CREATE FUNCTION [dbo].[SDF_SplitString]
(
    @sString nvarchar(2048),
    @cDelimiter nchar(1)
)
RETURNS @tParts TABLE ( part nvarchar(2048) )
AS
BEGIN
    if @sString is null return
    declare @iStart int,
            @iPos int
    if substring( @sString, 1, 1 ) = @cDelimiter 
    begin
        set @iStart = 2
        insert into @tParts
        values( null )
    end
    else 
        set @iStart = 1
    while 1=1
    begin
        set @iPos = charindex( @cDelimiter, @sString, @iStart )
        if @iPos = 0
            set @iPos = len( @sString )+1
        if @iPos - @iStart > 0          
            insert into @tParts
            values  ( substring( @sString, @iStart, @iPos-@iStart ))
        else
            insert into @tParts
            values( null )
        set @iStart = @iPos+1
        if @iStart > len( @sString ) 
            break
    end
    RETURN

END

En SQL Server 2008 puedes lograr lo mismo con el código .NET. Tal vez funcionaría más rápido, pero definitivamente este enfoque es más fácil de gestionar.

XOR avatar Mar 30 '2009 14:03 XOR

Ha etiquetado este SQL Server 2008, pero los futuros visitantes de esta pregunta (que utilicen SQL Server 2016+) probablemente querrán conocer STRING_SPLIT.

Con esta nueva función incorporada ahora puedes usar

SELECT TRY_CAST(value AS INT)
FROM   STRING_SPLIT ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15', ',') 

Algunas restricciones de esta función y algunos resultados prometedores de las pruebas de rendimiento se encuentran en esta publicación de blog de Aaron Bertrand .

Martin Smith avatar Mar 19 '2016 20:03 Martin Smith

Esto se parece mucho a .NET, para aquellos que estén familiarizados con esa función:

CREATE FUNCTION dbo.[String.Split]
(
    @Text VARCHAR(MAX),
    @Delimiter VARCHAR(100),
    @Index INT
)
RETURNS VARCHAR(MAX)
AS BEGIN
    DECLARE @A TABLE (ID INT IDENTITY, V VARCHAR(MAX));
    DECLARE @R VARCHAR(MAX);
    WITH CTE AS
    (
    SELECT 0 A, 1 B
    UNION ALL
    SELECT B, CONVERT(INT,CHARINDEX(@Delimiter, @Text, B) + LEN(@Delimiter))
    FROM CTE
    WHERE B > A
    )
    INSERT @A(V)
    SELECT SUBSTRING(@Text,A,CASE WHEN B > LEN(@Delimiter) THEN B-A-LEN(@Delimiter) ELSE LEN(@Text) - A + 1 END) VALUE      
    FROM CTE WHERE A >0

    SELECT      @R
    =           V
    FROM        @A
    WHERE       ID = @Index + 1
    RETURN      @R
END

SELECT dbo.[String.Split]('121,2,3,0',',',1) -- gives '2'
Todd avatar Jul 06 '2011 00:07 Todd