T-SQL 搜索和替换模式

T-SQL Search and replace pattern

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

removethis<removethis@xx.com>; andthis<andthis@xx.com>; nothis@yy.com; butthis<butthis@xx.com>

我只想 return 一个以分号分隔的电子邮件地址列表,这样我要查找的输出将是这样的

删除这个@xx.com;andthis@xx.com;nothis@yy.com;butthis@xx.com

我想在 T-SQL 函数中实现它,这样我就可以在可能的情况下重用它。

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

之间的内容

信息: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)

预期输出:

removethis@xx.com;andthis@xx.com;nothis@yy.com;butthis@xx.com

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

尽管如此,您可以通过以下几个步骤完成此操作:

  • 将字符串拆分为 ;
  • Trim 个空格
  • >替换为空
  • 找到 < 的位置(如果有的话)
  • 取从那个字符开始的子串,如果none
  • 则取整个字符串
  • 汇总备份
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)

您可以使用 string_splitstring_agg 以及 stuff 的组合来删除每个“<”之前的所有字符。

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,';')

请尝试以下解决方案。

它利用了从 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 |
+------------------------------------------------------------------------------------------------+---------------------------------------------------------------+