【问题标题】:T-SQL Search and replace patternT-SQL 搜索和替换模式
【发布时间】:2021-05-24 13:20:35
【问题描述】:

我的大脑今天不工作了。我有一个字符串,其中包含一个逗号分隔的电子邮件地址列表,类似于下面

删除这个; andthis; nothis@yy.com;但这

我只想返回一个以分号分隔的电子邮件地址列表,因此我正在寻找的输出将是这样的

删除this@xx.com;andthis@xx.com;nothis@yy.com;butthis@xx.com

我想在 T-SQL 函数中实现这一点,因此如果可能的话我可以重用它。

如上例所示,通过的列表可以只是一个电子邮件地址,也可以是一个名称后跟电子邮件。逻辑需要检查它是否只是一封电子邮件,然后返回它,如果它是一个名称和一封电子邮件(由模式名称 电子邮件 > 表示,那么只需返回

供参考:SQL 版本:Azure SQL 数据库

示例场景:

DECLARE @X varchar(max) = '
removethis<removethis@xx.com>;andthis<andthis@xx.com>;nothis@yy.com;butthis<butthis@xx.com>'
Select @udfFormatEmail(@X)

预期输出:

删除this@xx.com;andthis@xx.com;nothis@yy.com;butthis@xx.com

【问题讨论】:

  • 不要在 T-SQL 中这样做;使用支持正则表达式替换的东西(或“投资”在支持的 CLR 函数中)。
  • 在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:stackoverflow.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上面#1 中的样本数据。 (4) 你的 SQL Server 版本 (SELECT @@version;)
  • @Larnu - 我仅限于我可以使用此解决方案,但是是的,我同意使用另一种技术会更容易
  • @YitzhakKhabinsky - 详细信息已在通话中 - 技术 - Azure SQL,问题末尾提供了可复制示例,并提供预期输出
  • @user7415753,请明确提供##1-4。 “...我有一个字符串,在 SQL Server 表列中有一个逗号分隔的电子邮件地址列表...”。它在哪里?

标签: sql-server tsql azure-sql-database azure-sql-server


【解决方案1】:

您可以使用string_splitstring_aggstuff 的组合来删除每个“

declare @X varchar(max) ='removethis<removethis@xx.com>;andthis<andthis@xx.com>;nothis@yy.com;butthis<butthis@xx.com>'

select String_Agg(Replace(Stuff(value,1, CharIndex('<',value),''),'>',''),';')
from String_Split(@X,';')

【讨论】:

    【解决方案2】:

    您确实不应该在同一列中存储多条信息,这既适用于多封电子邮件,也适用于电子邮件名称和值。

    尽管如此,您可以通过多个步骤来做到这一点:

    • ;分割字符串
    • 修剪空格
    • &gt; 替换为空
    • 找到&lt;的位置(如果有)
    • 取其后开始字符的子字符串,如果没有则取整个字符串
    • 聚合备份
    SELECT STRING_AGG(
        ISNULL(
            SUBSTRING(v1.email, v2.leftArrow + 1, LEN(v1.email)),
            v1.email
       ), ';')
    FROM YourTable t
    CROSS APPLY STRING_SPLIT(t.emails, ';') s
    CROSS APPLY (VALUES (REPLACE(TRIM(s.value), '>', '')     )) v1(email)
    CROSS APPLY (VALUES (NULLIF(CHARINDEX('<', v1.email), 0) )) v2(leftArrow)
    

    【讨论】:

    • 我喜欢这个答案,但接受了 Stu 的回答,因为它提供了一种更简单的方法来实现我所追求的目标。
    【解决方案3】:

    请尝试以下解决方案。

    它利用了从 SQL Server 2017 开始可用的 TRIM() 函数的高级功能。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE  (ID INT IDENTITY PRIMARY KEY, emailList VARCHAR(MAX));  
    INSERT INTO @tbl (emailList) VALUES
    ('removethis<removethis@xx.com>; andthis<andthis@xx.com>; nothis@yy.com; butthis<butthis@xx.com>');
    -- DDL and sample data population, end
    
    SELECT a.emailList
        , STRING_AGG(TRIM('<> ' FROM RIGHT(value, LEN(value) - pos)), ';') AS cleansedEmailList
    FROM @tbl AS a
        CROSS APPLY STRING_SPLIT(emailList, ';')
        CROSS APPLY (SELECT CHARINDEX('<', value)) AS t(pos)
    GROUP BY a.emailList;
    

    输出

    +------------------------------------------------------------------------------------------------+---------------------------------------------------------------+
    |                                           emailList                                            |                       cleansedEmailList                       |
    +------------------------------------------------------------------------------------------------+---------------------------------------------------------------+
    | removethis<removethis@xx.com>; andthis<andthis@xx.com>; nothis@yy.com; butthis<butthis@xx.com> | removethis@xx.com;andthis@xx.com;nothis@yy.com;butthis@xx.com |
    +------------------------------------------------------------------------------------------------+---------------------------------------------------------------+
    

    【讨论】:

      猜你喜欢
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 2011-05-22
      • 2011-08-16
      • 2016-03-15
      • 2013-10-17
      相关资源
      最近更新 更多