热将值为 '1,2,3' 的变量转换为 table(每个数字作为记录)

Hot to convert a variable with value '1,2,3' to a table (every number as a record)

  1. 致力于 SQL(2005 年和 2008 年)

  2. 值为“1,2,3”的变量将调用@cedis,例如这可能有 N 个数字

    set @cedis='1' or set @cedis='1,2,3,4,5,6,7' or set @cedis='125,98,91'
    
  3. 这么重要,这个必须是select而已,不能用循环,只有select!

  4. 这必须 return a(结果为)table,例如

    set @cedis='1,2,3,4' this must to return a result 
    number 1 2 3 4
    
    declare @cedis varchar(max)
    set @cedis='1,58,123,8'
    ;with datos as 
    (
       my select with is going to return me the table
    )
    select * from datos 
    

结果集是

number
1
58
123
8

如果我没记错,这就是你需要的

DECLARE @cedis VARCHAR(500)='1,2,3,4'

SELECT Split.a.value('.', 'VARCHAR(100)') Numbers
FROM   (SELECT Cast ('<M>' + Replace(@cedis, ',', '</M><M>') + '</M>' AS XML) AS Numbers) AS A
       CROSS APPLY Numbers.nodes ('/M') AS Split(a) 

结果:

Numbers
-------
1
2
3
4

一个table值函数就可以做到。

CREATE FUNCTION [dbo].[fn_Split](@text VARCHAR(MAX), @delimiter VARCHAR(5) = ',')
RETURNS @Strings TABLE
(    
    position int IDENTITY PRIMARY KEY,
    value VARCHAR(8000)  
)
AS
BEGIN
    DECLARE @index int 
    SET @index = -1 
    WHILE (LEN(@text) > 0) 
        BEGIN  
            SET @index = CHARINDEX(@delimiter , @text)  
            IF (@index = 0) AND (LEN(@text) > 0)  
                BEGIN   
                    INSERT INTO @Strings VALUES (@text)
                    BREAK  
                END  
            IF (@index > 1)
                BEGIN
                    INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))
                END
            SET @text = RIGHT(@text, (LEN(@text) - (@index+LEN(@delimiter)-1))) 
        END
    RETURN
END

您可以这样调用:

SELECT *
FROM dbo.fn_Split(@cedis,',')

这是一个更通用的解决方案,它根据任何给定的分隔符将任何给定的字符串分解为 table:

http://rextester.com/VSRDLS48817

不是原创,但我发现它非常有用。

create function [dbo].[SplitString] 
(
    @str nvarchar(255), 
    @separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
    select 
        cast(1 as int), 
        cast(1 as int), 
        charindex(@separator, @str)
    union all
    select
        p + 1, 
        b + 1, 
        charindex(@separator, @str, b + 1)
    from tokens
    where b > 0
)
select
    p-1 ItemIndex,
    substring(
        @str, 
        a, 
        case when b > 0 then b-a ELSE LEN(@str) end) 
    AS Item
from tokens
);

这是获得所需输出结果的另一种方法

DECLARE @cedis VARCHAR(MAX) ,
@delimeter VARCHAR(10)

SET @cedis = '1,58,123,8,14144,15,155231,15,3647,2347,45,76,68,2354,577,5'
SET @delimeter = ','
SET @cedis = @cedis + @delimeter;
WITH    datos
          AS ( SELECT   n = 1
               UNION ALL
               SELECT   n + 1
               FROM     datos
               WHERE    n <= LEN(@cedis)
             ),
        cte
          AS ( SELECT   T.N ,
                        ROW_NUMBER() OVER ( ORDER BY T.N ) AS RN
               FROM     datos AS T
               WHERE    SUBSTRING(@cedis, T.N, LEN(@delimeter)) = @delimeter
                        AND LEN(@cedis) >= T.N
             )
    SELECT  SUBSTRING(@cedis, COALESCE(R.N + LEN(@delimeter), 1),
                      L.N - COALESCE(R.N + LEN(@delimeter), 1)) AS part ,
            L.RN AS ID
    FROM    cte AS L
            LEFT JOIN cte AS R ON L.RN = R.RN + 1
OPTION  ( MAXRECURSION 1000 )