• What a useful trick, and definitely something I'll need to remember.

    However, I think the function has a bug.  When I put through either of the following...

    SELECT

    * FROM dbo.fnSetSplit(',C,,,E')

    SELECT

    * FROM dbo.fnSetSplit(',,C,,,E')

    ...I get odd results before 'C'.  Instead, I knocked up the below with some adjustments:

    i) the Numbers table starts from 0, not 1

    ii) accepts a variable delimiter, including one of variable length;

    iii) returns a row number so that you can choose the nth value.

    iv) use "like" for comparisons as SQL Server can do funny things comparing spaces

    It does have a "quirk", however.  If the delimiter is a multiple of the same character you can get odd results.  Whether this is an error or not I think depends on the expected usage.

    SELECT

    * FROM dbo.fnSetSplitSV(',,C,,,E',',') -- picks up the "missing" A

    SELECT

    * FROM dbo.fnSetSplitSV(' TA fred TA mary TA albert',' TA ') -- variable delimiter

    SELECT

    * FROM dbo.fnSetSplitSV(',,,C,,,E',',,') -- multiple delimiter with "quirk"

    S.

    (Sorry if the below comes over with screwy formatting.)
     

    CREATE FUNCTION [dbo].[fnSetSplitSV] (@String VARCHAR(8000), @Delim VARCHAR(5))

    RETURNS

    @SplitTable TABLE

    (

    Row

    int identity

    , Num int

    , String varchar(8000)

    )

    AS

    BEGIN

    DECLARE @DelimLen int

    SELECT @DelimLen = datalength(@Delim)

    INSERT INTO @SplitTable

    SELECT

    Num

    , SUBSTRING(@String

    , CASE Num + @DelimLen

    WHEN @DelimLen THEN @DelimLen

    ELSE Num + @DelimLen

    END - @DelimLen

    , CASE CHARINDEX(@Delim, @String, Num)

    WHEN 0 THEN LEN(@String) - Num + @DelimLen

    ELSE CHARINDEX(@Delim, @String, Num) - Num

    END

    ) AS String

    FROM dbo.Numbers

    WHERE Num <= LEN(@String)

    AND (SUBSTRING(@String, Num - @DelimLen, @DelimLen) like @Delim OR Num = 0)

    RETURN

    END