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_split
和 string_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 |
+------------------------------------------------------------------------------------------------+---------------------------------------------------------------+
我的大脑今天不工作了。我有一个字符串,其中有一个逗号分隔的电子邮件地址列表,类似于下面
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_split
和 string_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 |
+------------------------------------------------------------------------------------------------+---------------------------------------------------------------+