【问题标题】:How to insert a comma in between a string如何在字符串之间插入逗号
【发布时间】:2019-05-09 07:52:35
【问题描述】:

我有一个字符串,我需要在给定的字符串之间插入一个逗号。请帮我出出主意

declare @a varchar(15) = 'asdfghj'
select @a

我希望输出为'a,s,d,f,g,h,j'

【问题讨论】:

  • 一开始就不要在 SQL 中这样做。 SQL这种语言在字符串操作方面非常差。为什么你首先要这样做?你想做什么,这个字符串是从哪里来的?也许有更好的方法来做任何你想做的事情,而不涉及字符串操作
  • 递归 cte?
  • 下面的答案可能会对您有所帮助,但无论您使用什么,它都会显着降低您的查询速度。为什么不在应该完成的表示层中执行此操作
  • 我想很多人都有这个确切的问题。我不同意关闭的建议,也不同意所有的反对票。我希望这包含在 sql server 2016 的 string_split 中

标签: sql sql-server sql-server-2008-r2


【解决方案1】:

这将在 sql server 2008 中工作

DECLARE @a varchar(max)='23'
DECLARE @b INT=len(@a)

WHILE @b>1
SELECT @a=stuff(@a,@b,0,','),@b-=1

SELECT @a

如果你曾经升级到 sql server 2017,你可以使用这个版本,假设字符串不超过 2047 个字符(2047 是 spt_values 中 type=P 的最大数字,否则你可以使用数字表或类似的东西):

DECLARE @a varchar(max)='abcd'

SELECT string_agg(substring(@a,number+1,1),',')
FROM master..spt_values
WHERE number < len(@a)
and type='P'

【讨论】:

    【解决方案2】:

    SQL Server 并非设计用于执行此操作,但这里有一种在 while 循环中执行此操作的简单方法;

        DECLARE @a varchar(15) = 'asdfghj'
        DECLARE @i int = 1
        DECLARE @output varchar(30)
    
        WHILE (@i <= len(@a))
        BEGIN
            SET @output = ISNULL(@output,'') + ',' + SUBSTRING(@a, @i, 1)
            SET @i = @i + 1
        END
    
        SET @output = STUFF(@output,1,1,'')
    
        SELECT @output
    

    输出:a,s,d,f,g,h,j

    它接受输入的每个单独字符并在其前面插入一个逗号。 STUFF 函数会删除字符串中的第一个逗号,如果您愿意,可以使用 SUBSTRINGRIGHT 来执行此操作。

    如果您调整 @a 和 @output 的长度,这将适用于您传入的任何长度字符串

    【讨论】:

    • 您可以使用this 方法稍微改进您的答案(不要告诉任何人)
    【解决方案3】:

    仔细考虑 Panagiotis Kanavos 的评论,但如果您想使用 T-SQL 执行此操作,一种可能的方法是使用递归 CTE 和 FOR XML(受 SQL Server 2008 支持):

    DECLARE @a varchar(15) = 'asdfghj'
    
    ;WITH cte AS (
        SELECT SUBSTRING(@a, 1, 1) AS Symbol, 1 AS Position
        UNION ALL
        SELECT SUBSTRING(@a, Position + 1, 1), Position + 1
        FROM cte
        WHERE Position < LEN(@a)
    )
    SELECT STUFF((
        SELECT CONCAT(N',',  Symbol)
        FROM cte
        ORDER BY Position
        FOR XML PATH('')
    ), 1, 1, N'') AS Result
    OPTION (MAXRECURSION 0)
    

    输出:

    Result
    a,s,d,f,g,h,j
    

    注意事项: 仅供参考,从 SQL Server 2017 开始,您可以使用STRING_AGG()

    DECLARE @a varchar(15) = 'asdfghj'
    
    ;WITH cte AS (
        SELECT SUBSTRING(@a, 1, 1) AS Symbol, 1 AS Position
        UNION ALL
        SELECT SUBSTRING(@a, Position + 1, 1), Position + 1
        FROM cte
        WHERE Position < LEN(@a)
    )
    SELECT STRING_AGG(Symbol, ',')
    FROM cte
    OPTION (MAXRECURSION 0)
    

    【讨论】:

      【解决方案4】:

      正如已经提到的,这是一个糟糕的主意。

      如果可以避免,请不要在 SQL Server 中执行此操作。

      也就是说,如果由于某种原因无法避免,则基于集合的解决方案将涉及数字表。如果您没有其中之一,您可以使用cte 以很少的开销生成一个。要仅使用一个值,您可以这样做:

      declare @a varchar(15) = 'asdfghj';
      
      with t(t)as(select t from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))as t(t))
          ,n(n)as(select top(len(@a)) row_number()over(order by(select null)) from t,t t2,t t3,t t4)
      select @a = stuff((select ',' + substring(@a,n,1)
                         from n
                         order by n
                         for xml path('')
                        )
                       ,1,1,''
                       );
      
      select @a;
      

      哪个输出:a,s,d,f,g,h,j

      或者将此逻辑应用于值表,您可以执行以下操作:

      declare @t table (a varchar(100));
      insert into @t values('asdfghj'),('qwerty'),('qwertyuiopasdfghjklzxcvbnm[];#?|');
      
      with t(t)as(select t from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))as t(t))
          ,n(n)as(select top(select max(len(a)) from @t) row_number()over(order by(select null)) from t,t t2,t t3,t t4)
      select stuff((select ',' + substring(a,n,1)
                    from n
                    where n.n <= len(t.a)
                    order by n.n
                    for xml path('')
                   )
                  ,1,1,''
                  ) as CommaDelimited
      from @t as t;
      

      哪些输出:

      +---------------------------------------------------------------------------+
      |                              CommaDelimited                               |
      +---------------------------------------------------------------------------+
      | a,s,d,f,g,h,j                                                             |
      | q,w,e,r,t,y                                                               |
      | q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m,[,],;,#,?,|           |
      +---------------------------------------------------------------------------+
      

      【讨论】:

        【解决方案5】:

        希望这可行,我使用 STUFF() 函数插入 ,

            declare @a varchar(15) = 'asdfghj'
            declare @totalchar int = len(@a)
            declare @counter int = @totalchar
        
            while @counter >=1
            begin 
                    if @counter + 1 <= @totalchar
                    begin
                         set @a = stuff(@a,@counter + 1, 0 , ',')
                    end
                    set @counter = @counter -1
            end
        
            select @a
        

        【讨论】:

          【解决方案6】:

          我非常同意 Panagiotis Kanavos 的评论。以下 sn-p 将为您工作。

          Declare @a varchar(15) = 'asdfghj',@OUTPUT VARCHAR(MAX)= ''
          
          SELECT @OUTPUT = @OUTPUT+AA+',' FROM (
          SELECT number ,SUBSTRING(@a, number, 1) AA
          FROM master.DBO.spt_values WHERE TYPE = 'P'
          AND number BETWEEN 1 AND LEN(@a)
          )A
          Order by number
          
          SELECT SUBSTRING(@OUTPUT,1,LEN(@OUTPUT)-1)
          

          我使用了spt_values,这是微软未记录的,不是首选。您可以尝试使用 Numbers 表进行相同的操作。

          【讨论】:

            【解决方案7】:

            试试这个简单的方法...

            DECLARE @INPUT VARCHAR(10) = 'ABCD'
            DECLARE @i INT = 1
            DECLARE @OUTPUT VARCHAR(50) = ''
            
            WHILE @I < = LEN(@INPUT)
            BEGIN
                SET @OUTPUT = @OUTPUT + SUBSTRING(@INPUT,@i,1) + ','
                SET @i = @i + 1
            END
            SET @OUTPUT = SUBSTRING(@OUTPUT,1,LEN(@OUTPUT) - 1)
            PRINT @OUTPUT
            

            【讨论】:

            • 复制别人的答案并重新发布并进行非常小的更改通常被认为是不好的形式。
            • 亲爱的@Rich Benner。这是我自己的代码。我没有抄兄弟。
            最近更新 更多