【问题标题】:Split string in database row and copy results to different rows - SQL Server在数据库行中拆分字符串并将结果复制到不同的行 - SQL Server
【发布时间】:2010-06-22 23:23:56
【问题描述】:

我创建了一个应用程序来向用户发送邮件。 我正在使用一个数据库,其中一些用户分配了多个电子邮件地址。

Name                        Mail
-----------------------------------------
BusinessXPTO     mail1@xpto.com;mail2@xpto.com

电子邮件列可以包含多个电子邮件,以分号分隔。 我想拆分字符串,以便将每封电子邮件放在不同的行上。

Name                        Mail
-----------------------------------------
BusinessXPTO         mail1@xpto.com
BusinessXPTO         mail2@xpto.com

什么是最好的解决方案?

谢谢

【问题讨论】:

  • 打印屏幕,另存为JPEG(最大压缩),打印为PDF(600dpi),打印硬拷贝(收发室打印机),发送给秘书(行政助理),接收Word文档(Times New Roman),复制到 Excel(格式为数字),编写公式生成 SQL(="insert TheTable select '" & $A2 & "'"),将单元格复制到 SQL 工作台/工作室(祈祷)。

标签: sql-server string split


【解决方案1】:

这是一个使用 SQL Server 2005 及更高版本中的 XML 功能的简单示例。我从here 逐字逐句提取了它,但是如果你用谷歌搜索“split string sql server xml”会有很多例子

DECLARE @xml as xml,@str as varchar(100),@delimiter as varchar(10)
SET @str='A,B,C,D,E'
SET @delimiter =','
SET @xml = cast(('<X>'+replace(@str,@delimiter ,'</X><X>')+'</X>') as xml)
SELECT N.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as T(N)

还有其他带有光标的解决方案,但这种方法对我来说效果很好。

【讨论】:

    【解决方案2】:

    以下是我用来在任意分隔符上拆分值的 UDF。此后,我修改了我的函数,使其成为内联表函数(而不是多语句表函数),并且在动态构建时不再依赖 Numbers 表。

    CREATE FUNCTION dbo.udf_Split
    (   
        @DelimitedList nvarchar(max)
        , @Delimiter nvarchar(2) = ','
    )
    RETURNS TABLE 
    AS
    RETURN 
        (
        With CorrectedList As
            (
            Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
                + @DelimitedList
                + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
                As List
                , Len(@Delimiter) As DelimiterLen
            )
            , Numbers As 
            (
            Select Row_Number() Over ( Order By c1.object_id ) As Value
            From sys.columns As c1
                Cross Join sys.columns As c2
            )
        Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
            , Substring (
                        CL.List
                        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen     
                        , CharIndex(@Delimiter, CL.list, N.Value + 1)                           
                            - ( CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen ) 
                        ) As Value
        From CorrectedList As CL
            Cross Join Numbers As N
        Where N.Value < Len(CL.List)
            And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
        )
    

    这是一个示例调用:

    Select T.Name, Address.Value
    From MyTable As T
        Cross Apply dbo.udf_Split( T.Mail, ';' ) As Addresses
    

    【讨论】:

      【解决方案3】:

      在甲骨文中

      这里是提供的示例的模拟:

      select 'BusinessXPTO' name, 'mail1@xpto.com;mail2@xpto.com' mail from dual;
      

      以下是如何将 ma​​il 列拆分为单独的行

      select 'BusinessXPTO' name, regexp_substr('mail_1@xpto.com;mail_2@xpto.com','[^;]+',1, rn) mail  
      from dual 
      cross join 
          (select rownum rn from 
              (select max(length(regexp_replace('mail_1@xpto.com;mail_2@xpto.com', '[^;]+'))) + 1 mx from dual) 
          connect by level <= mx ) 
      where regexp_substr ('mail1@xpto.com;mail2@xpto.com', '[^;]+', 1, rn) is not null 
      order by rn;
      

      这是结果

      NAME            MAIL
      BusinessXPTO    mail_1@xpto.com
      BusinessXPTO    mail_2@xpto.com
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多