【问题标题】:How to split string and insert values into table in SQL Server如何在 SQL Server 中拆分字符串并将值插入表中
【发布时间】:2013-11-10 01:00:15
【问题描述】:

我有一个这样的字符串:

72594206916,2,1/2/08,Tacoma,WA:72594221856,5,5/7/13,San Francisco,CA:72594221871,99,12/30/12,Dallas,TX

这基本上是 3 行中的每一行中的 5 个值(来自 ASP.NET 网格)。我需要在 SQL Server 表中将此字符串拆分为 5 列和 3 行。单个值用逗号分隔,行用冒号分隔。

我找到了一个将字符串分割成片段的函数,我可以从这个字符串中取出行:

declare @testString varchar(100)
set @testString = '72594206916,2,1/2/08,Tacoma,WA:72594221856,5,5/7/13,San Francisco,CA:72594221871,99,12/30/12,Dallas,TX'

select *
from dbo.SplitString(@testString, ':')

给我:

72594206916,2,1/2/08,Tacoma,WA
72594221856,5,5/7/13,San Francisco,CA
72594221871,99,12/30/12,Dallas,TX

这给了我一个包含三行的结果集(函数输出一个表)。我可以同时再次调用这个函数并以某种方式将其输出插入到表中吗?

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    假设您的拆分返回列名item

    insert <table> (colname)
    select y.item
    from dbo.SplitString(@testString, ':') x
    cross apply
    dbo.SplitString(x.item, ',') y
    

    【讨论】:

      【解决方案2】:

      函数定义,Romil
      在你的 Sql Server 中创建这个函数

      CREATE FUNCTION Split (
            @InputString                  VARCHAR(8000),
            @Delimiter                    VARCHAR(50)
      )
      
      RETURNS @Items TABLE (
            Item                          VARCHAR(8000)
      )
      
      AS
      BEGIN
            IF @Delimiter = ' '
            BEGIN
                  SET @Delimiter = ','
                  SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
            END
      
            IF (@Delimiter IS NULL OR @Delimiter = '')
                  SET @Delimiter = ','
      
      --INSERT INTO @Items VALUES (@Delimiter) -- Diagnostic
      --INSERT INTO @Items VALUES (@InputString) -- Diagnostic
      
            DECLARE @Item                 VARCHAR(8000)
            DECLARE @ItemList       VARCHAR(8000)
            DECLARE @DelimIndex     INT
      
            SET @ItemList = @InputString
            SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
            WHILE (@DelimIndex != 0)
            BEGIN
                  SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
                  INSERT INTO @Items VALUES (@Item)
      
                  -- Set @ItemList = @ItemList minus one less item
                  SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
                  SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
            END -- End WHILE
      
            IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString
            BEGIN
                  SET @Item = @ItemList
                  INSERT INTO @Items VALUES (@Item)
            END
      
            -- No delimiters were encountered in @InputString, so just return @InputString
            ELSE INSERT INTO @Items VALUES (@InputString)
      
            RETURN
      
      END -- End Function
      GO
      

      传递你的参数
      由于它是一个表函数,您将像处理表一样 SELECT * FROM this_Function

      declare @testString varchar(100)
      set @testString = '72594206916,2,1/2/08,Tacoma,WA:72594221856,5,5/7/13,San Francisco,CA:72594221871,99,12/30/12,Dallas,TX'
      
      SELECT * FROM Split(@testString, ',')
      

      结果集

      Item
      72594206916
      2
      1/2/08
      Tacoma
      WA:72594221856
      5
      5/7/13
      San Francisco
      CA:72594221871
      99
      12/30/12
      Dallas
      

      您现有的代码

      select *
      from dbo.SplitString(@testString, ':')
      

      第二个参数需要是分隔符,因为您将 : 作为第二个参数传递,所以它会在您传递的字符串中找到 : 时破坏您的字符串,这显然在 2 个位置,您会返回 3结果集中的值/字符串

                                String1/Value1                             String2/Value2                    String3/Value3
      set @testString = '72594206916,2,1/2/08,Tacoma,WA  :   72594221856,5,5/7/13,San Francisco,CA  :  72594221871,99,12/30/12,Dallas,TX'
      

      【讨论】:

      • 很棒的代码:只是一个小注释 - 你需要写 'declare @testString varchar(102)' 而不是 varchar(100) 否则 TX 会被错过!
      【解决方案3】:

      创建这个 SQL 函数:

      CREATE FUNCTION [dbo].[StringSplit](@input NVARCHAR(MAX), @delimiter CHAR(1)=',') 
             RETURNS @returnTable TABLE(item NVARCHAR(100)) AS  
           BEGIN 
              IF @input IS NULL RETURN;
              DECLARE @currentStartIndex INT, @currentEndIndex INT,@length INT;
              SET @length=LEN(@input);
              SET @currentStartIndex=1;
      
              SET @currentEndIndex=CHARINDEX(@delimiter,@input,@currentStartIndex);
              WHILE (@currentEndIndex<>0)
                BEGIN
                  INSERT INTO @returnTable VALUES (LTRIM(SUBSTRING(@input, @currentStartIndex, @currentEndIndex-@currentStartIndex)))
                  SET @currentStartIndex=@currentEndIndex+1;
                  SET @currentEndIndex=CHARINDEX(@delimiter,@input,@currentStartIndex);
                END
      
              IF (@currentStartIndex <= @length)
                INSERT INTO @returnTable 
                  VALUES (LTRIM(SUBSTRING(@input, @currentStartIndex, @length-@currentStartIndex+1)));
              RETURN;
           END;
      

      用法示例:

      DECLARE @testString VARCHAR(100)
      SET @testString = '72594206916,2,1/2/08,Tacoma,WA:72594221856,5,5/7/13,San Francisco,CA:72594221871,99,12/30/12,Dallas,TX'
      
      SELECT *
      FROM [dbo].[StringSplit](@testString, DEFAULT)
      

      结果(表格):

      72594206916
      2
      1/2/08
      Tacoma
      WA:72594221856
      5
      5/7/13
      San Francisco
      CA:72594221871
      99
      12/30/12
      Dallas
      

      【讨论】:

        【解决方案4】:

        类似于上面 M.Ali 给出的内容,但更短:

        Use [Database_Name]
        Go;
        
         CREATE FUNCTION Split
        (
        @RowData nvarchar(MAX),
        @SplitOn nvarchar(MAX)
        )  
        RETURNS @RtnValue table 
        (
        Data nvarchar(MAX)
        ) 
        AS  
        BEGIN 
        Declare @Cnt int
        Set @Cnt = 1
        
        While (Charindex(@SplitOn,@RowData)>0)
        Begin
            Insert Into @RtnValue (data)
            Select 
                Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))
        
            Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
            Set @Cnt = @Cnt + 1
        End
        
        Insert Into @RtnValue (data)
        Select Data = ltrim(rtrim(@RowData))
        
        Return
        END
        

        然后像上例那样从函数中选择:

        USE [Database_Name]
        GO
        declare @testString varchar(100)
        set @testString = '72594206916,2,1/2/08,Tacoma,WA:72594221856,5,5/7/13,San   Francisco,CA:72594221871,99,12/30/12,Dallas,TX'
        
        SELECT * FROM Split(@testString, ',')
        

        【讨论】:

          【解决方案5】:
          declare @fqdn_list varchar(max) = 'test1.qa.local,test2.qa.local,test3.qa.local'
          -- temp table
          DECLARE @fqdn_tbl TABLE (   fqdn nvarchar(50) )
          
          INSERT INTO @fqdn_tbl  SELECT LTRIM(RTRIM(split.a.value('.', 'NVARCHAR(MAX)'))) AS fqdn   FROM (
              SELECT CAST ('<M>' + REPLACE(@fqdn_list, ',', '</M><M>') + '</M>' AS XML) AS data   ) AS a   CROSS APPLY data.nodes ('/M') AS split(a)
          
          select * from  @fqdn_tbl
          

          【讨论】:

            【解决方案6】:

            如果您的数据库兼容 130 或更高版本,您可以使用内置函数 STRING_SPLIT:

            https://database.guide/how-to-convert-a-comma-separated-list-into-rows-in-sql-server/

            【讨论】:

            • 也许可以通过一个小代码示例来改进答案。另外:如果兼容性
            • 这是一个提示,不是完整的答案,因此适合发表评论。
            【解决方案7】:

            试试这个代码:

            SELECT value
            FROM STRING_SPLIT(@testString, ',')
            

            【讨论】:

              【解决方案8】:

              你忘记了最后一行。在您的示例中,未考虑“TX”。你应该检查剩余的文本 avec While 循环

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-03-30
                • 2012-06-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多