【问题标题】:How can I insert each character of a string which is not comma delimited to separate row in a table?如何将不以逗号分隔的字符串的每个字符插入表中的单独行?
【发布时间】:2017-04-27 19:19:49
【问题描述】:

我有一个类似的字符串

Declare @Str varchar (15) = '0123456789' 

我有一张桌子

CREATE TABLE TableNum(Nums Varchar(1));

如何将每个数字插入单独的行?

我的输出应该是

Nums
0
1
2
3
4
.
.

【问题讨论】:

标签: sql-server sql-server-2008


【解决方案1】:

使用数字表可能是最好和最简单的方法。如果您还没有数字表,您可以创建一个:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Tally
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Tally ADD CONSTRAINT PK_Tally PRIMARY KEY CLUSTERED (Number)

那么你所要做的就是:

INSERT INTO TableNum(Nums)
SELECT SUBSTRING(@Str, Number, 1)
FROM Tally
WHERE Number <= LEN(@Str)

有关您为什么需要数字(或计数)表的更多信息,请阅读 Jeff Moden 的 this article

顺便说一句,使用 varchar(1) 没有意义 - 请改用 char(1)

【讨论】:

    【解决方案2】:

    试试这个:使用 CTE 你可以做到这一点,无需对现有系统表使用任何连接

    ;WITH CTE AS(
         SELECT CAST('' AS NVARCHAR(1)) AS CH, 1 AS CNT
         UNION ALL
         SELECT CAST(SUBSTRING(@Str,CNT,1)AS NVARCHAR(1)) AS CH , CNT+1
         FROM CTE 
         WHERE CNT<=LEN(@Str)
    )
    INSERT INTO TableNum(Nums) 
    SELECT CH FROM CTE WHERE CH <> ''
    

    【讨论】:

      【解决方案3】:

      如果您无法添加计数表(Zohar Peled 说明的方式),您可以使用临时计数表

      Declare @Str varchar (15) = '0123456789' 
      
      Select Num=substring(@Str,N,1)
       From (Select Top (Len(@Str)) N=Row_Number() Over (Order By (Select null)) From master..spt_values ) N
      

      返回

      Num
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
      

      另一种选择是创建 TVF

      Declare @Str varchar (15) = '0123456789' 
      
      Select * from [dbo].[udf-Str-Parse-Char](@Str) 
      

      UDF

      CREATE FUNCTION [dbo].[udf-Str-Parse-Char] (@String varchar(max))
      Returns Table
      As
      Return (
          with   cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
                 cte2(N) As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From cte1 a,cte1 b,cte1 c,cte1 d,cte1 e,cte1 f)
      
          Select RetSeq=N
                ,RetVal=Substring(@String,N,1) 
           From  cte2
      ) 
      --Max 1 Million Observations
      --Select * from [dbo].[udf-Str-Parse-Char]('this is a string') 
      

      【讨论】:

      • 我不懂人。为什么你的答案,你在哪里声明(用粗体,不少于)我的更好,而我的没有得到赞成?不要误会我的意思,我认为你的答案很好,但我不禁想知道......嗯,在那里。我已经吐槽完了。
      • @ZoharPeled 我实际上是想支持你的答案,因为我确实支持计数表方法。如果 OP 无法创建表,我只提供了一个替代方案。也就是说,有些人永远不会看到一种方法相对于另一种方法的真正或未来价值。你可以把马牵到水边……
      • @ZoharPeled 如果它能让你感觉更好stackoverflow.com/questions/43654697/…
      【解决方案4】:
      Declare @Str varchar (15) = '0123456789' 
              ,@pos INT, 
               @result VARCHAR(100); 
      
         SET @result = @Str; 
         SET @pos = 2 -- location where we want first space 
         WHILE @pos < LEN(@result)+1 
         BEGIN 
             SET @result = STUFF(@result, @pos, 0, SPACE(1)); 
             SET @pos = @pos+2; 
      
        END
        SELECT @result=REPLACE( @result,' ',',')
        --Print @result
        SELECT   Split.a.value('.', 'VARCHAR(100)') AS Num  
              FROM  
              (
                  SELECT   
                       CAST ('<M>' + REPLACE(@result, ',', '</M><M>') + '</M>' AS XML) AS Num  
      
              ) AS A CROSS APPLY Num.nodes ('/M') AS Split(a)
      

      输出

      Num
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
      

      【讨论】:

        【解决方案5】:

        试试这个

        DECLARE @Str varchar(10) = '0123456789'
        DECLARE @Count INT=1
        
        WHILE @Count <= LEN(@Str)
        BEGIN
            INSERT INTO TableNum
            SELECT substring(@Str, @count, 1)  
            SET @Count = @Count + 1
        END
        

        然后

        SELECT * FROM TabNum
        

        【讨论】:

          【解决方案6】:

          试试这个。

          CREATE TABLE TableNum(Nums Varchar(1));
          TRUNCATE TABLE TableNum;
          
          Declare @Str varchar (15) = '0123456789';
          
          DECLARE @nLIMIT AS INT = LEN(@Str);
          DECLARE @nCounter AS INT = 1;
          
          WHILE @nCounter <= @nLIMIT
          BEGIN  
          
             INSERT INTO TableNum VALUES(SUBSTRING (@Str,@nCounter,1));
          
             SET @nCounter = @nCounter + 1;
             IF @nCounter > @nLIMIT
                   BREAK  
             ELSE  
                CONTINUE  
           END;
          
          SELECT * FROM TableNum;
          

          【讨论】:

            猜你喜欢
            • 2021-12-13
            • 2013-01-11
            • 2012-11-26
            相关资源
            最近更新 更多