【问题标题】:SQL Server: Split operationSQL Server:拆分操作
【发布时间】:2011-01-31 05:29:51
【问题描述】:

如何在 SQL Server 中拆分字符串。

例子:

输入字符串:stack over flow

结果:

stack
over
flow

【问题讨论】:

  • 为什么需要在数据库中做这个而不是使用你的客户端语言的内置拆分功能?你想解决什么问题?
  • 重复问题。你先检查了吗? - stackoverflow.com/questions/2647/split-string-in-sql
  • 是的,但该链接未标记为答案。

标签: sql-server-2008 split


【解决方案1】:

我知道这个问题是针对 SQL Server 2008 的,但事情会不断发展,所以从 SQL Server 2016 开始,您可以这样做

DECLARE @string varchar(100) = 'Richard, Mike, Mark'

SELECT value FROM string_split(@string, ',')

【讨论】:

    【解决方案2】:

    如果不能使用表值参数,请参见:"Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog ,那么在 SQL Server 中拆分字符串的方法有很多。本文涵盖了几乎所有方法的优缺点:

    "Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog

    您需要创建一个拆分函数。这就是拆分函数的使用方式:

    SELECT
        *
        FROM YourTable                               y
        INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
    

    I prefer the number table approach to split a string in TSQL 但在 SQL Server 中有多种拆分字符串的方法,请参阅上一个链接,其中解释了每种方法的优点和缺点。

    要使 Numbers Table 方法起作用,您需要执行此一次时间表设置,这将创建一个包含 1 到 10,000 行的表 Numbers

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

    一旦设置了 Numbers 表,创建这个拆分函数:

    CREATE FUNCTION [dbo].[FN_ListToTable]
    (
         @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
        ,@List     varchar(8000)--REQUIRED, the list to split apart
    )
    RETURNS TABLE
    AS
    RETURN 
    (
    
        ----------------
        --SINGLE QUERY-- --this will not return empty rows
        ----------------
        SELECT
            ListValue
            FROM (SELECT
                      LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                      FROM (
                               SELECT @SplitOn + @List + @SplitOn AS List2
                           ) AS dt
                          INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                      WHERE SUBSTRING(List2, number, 1) = @SplitOn
                 ) dt2
            WHERE ListValue IS NOT NULL AND ListValue!=''
    
    );
    GO 
    

    您现在可以轻松地将 CSV 字符串拆分为表格并加入表格:

    select * from dbo.FN_ListToTable(' ','stack over flow')
    

    输出:

    ListValue
    -------------------
    stack
    over
    flow
    
    (3 row(s) affected)
    

    【讨论】:

      【解决方案3】:
      CREATE FUNCTION [dbo].[Split]
      (
          @List varchar(max),
          @SplitOn nvarchar(5)
      )
      RETURNS @RtnValue table
      (
          Id int identity(1,1),
          Value nvarchar(max)
      )
      AS
      BEGIN
          While (Charindex(@SplitOn,@List)>0)
          Begin
      
              Insert Into @RtnValue (value)
              Select
              Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1)))
      
              Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List))
          End
      
          Insert Into @RtnValue (Value)
          Select Value = ltrim(rtrim(@List))
      
      Return
      END
      

      创建上面的函数并执行下面的查询来得到你的结果。

      Select * From Dbo.Split('Stack Over Flow',' ')
      

      建议:使用分隔符获取拆分值。它更好。 (例如“堆栈,溢出,流”)

      【讨论】:

        【解决方案4】:

        解决此类问题的一个常见的基于集合的解决方案是使用数字表。

        以下解决方案使用简单的递归 CTE 动态生成数字表 - 如果您需要处理更长的字符串,应将其替换为静态数字表。

        DECLARE @vch_string varchar(max)
        DECLARE @chr_delim char(1)
        SET @chr_delim = ' '
        SET @vch_string = 'stack over flow'
        
        ;WITH nums_cte
        AS
        (
          SELECT 1 AS n
          UNION ALL
          SELECT n+1 FROM nums_cte
          WHERE n < len(@vch_string)
        )
        SELECT n - LEN(REPLACE(LEFT(s,n),@chr_delim,'')) + 1 AS pos
               ,SUBSTRING(s,n,CHARINDEX(@chr_delim, s + @chr_delim,n) -n) as ELEMENT
        FROM (SELECT @vch_string as s) AS D
        JOIN nums_cte
        ON n <= LEN(s)
        AND SUBSTRING(@chr_delim + s,n,1) = @chr_delim
        OPTION (MAXRECURSION 0);
        

        【讨论】:

          【解决方案5】:

          很难。真的很难 - Strin 操作和 SQL ......糟糕的组合。 C#/.NET 对于存储过程是一种方式,可以返回一个表定义类型(表),每行一个项目。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-06-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多