正如 Martin 在 his answer 中所说,SQL Server 没有内置的 RegEx 功能(虽然这里没有建议,但要明确一点:不,LIKE 和 @987654329 的 [...] 通配符@ 是 不是 正则表达式)。如果您的数据几乎没有变化,那么可以,您可以使用一些 T-SQL 函数组合:REPLACE、SUBSTRING、LEFT、RIGHT、CHARINDEX、PATINDEX、FORMATMESSAGE、 CONCAT,也许还有一两个人。
但是,如果数据/输入甚至具有中等程度的复杂性,那么内置的 T-SQL 函数充其量是繁琐的,最坏的情况是无用的。在这种情况下,可以通过 SQLCLR 执行实际的 RegEx(只要您不使用 Azure SQL Database Single DB 或通过 AWS RDS 使用 SQL Server 2017+),这是在 SQL Server 中运行的(受限).NET 代码。您可以编写自己的代码/在 S.O. 上找到示例。或其他地方,或尝试一个预先完成的库,例如我创建的SQL# (SQLsharp),它的免费版本包含几个 RegEx 函数。请注意,作为 .NET 的 SQLCLR 不是基于 POSIX 的 RegEx,因此不使用 POSIX character classes(意思是:您需要将 \d 用于“数字”而不是 [:digit:])。
在这种特殊情况下所需的复杂程度尚不清楚,因为问题中的示例代码暗示数据简单且统一(即1112223333),但comment on the question 中显示的示例数据似乎表明存在可能是数据中的破折号和/或空格(即xxx- xxx xxxx)。
如果数据确实是统一的,那就坚持使用@MartinSmith 提供的纯T-SQL 解决方案。但是,如果数据足够复杂,那么请考虑下面的 RegEx 示例,使用我的SQL# 库的免费版本中的 SQLCLR 函数(如前所述),它可以轻松处理输入数据的 3 种变化等等:
SELECT SQL#.RegEx_Replace4k(tmp.phone,
N'\(?(\d{3})\)?[ .-]*(\d{3})[ .-]*(\d{4})', N'($1)$2-$3',
-1, -- count (-1 == unlimited)
1, -- start at
N'') -- RegEx options
FROM (VALUES (N'8885551212'),
(N'123- 456 7890'),
(N'(777) 555- 4653')
) tmp([phone]);
返回:
(888)555-1212
(123)456-7890
(777)555-4653
RegEx 模式允许:
- 0 或 1
(
- 3 个十进制数字
- 0 或 1
)
- 0 个或多个
、. 或 -
- 3 个十进制数字
- 0 个或多个
、. 或 -
- 4 位十进制数字
注意
有人提到较新的语言扩展可能是比 SQLCLR 更好的选择。语言扩展允许通过sp_execute_external_script 存储过程调用托管在 SQL Server 之外的 R / Python / Java 代码。正如Tutorial: Search for a string using regular expressions (regex) in Java 页面所示,外部脚本实际上不是SQL Server 中RegEx 的许多/大多数用途的好选择。主要问题是:
- 与 SQLCLR 不同,外部脚本的唯一接口是存储过程。这意味着您不能在查询中使用任何内联功能(
SELECT、WHERE 等)。
- 使用外部脚本,您可以传入查询,使用外部语言处理结果,然后传回静态结果集。这意味着编译后的代码现在必须更专业(即紧密耦合)到特定用途。更改查询使用 RegEx 的方式和/或返回的列现在需要编辑、编译、测试和部署 R / Python / Java 代码以及(和协调!)T-SQL变化。
我确信外部脚本绝对很棒,并且在某些情况下是比 SQLCLR 更好的选择。但它们当然不适合 RegEx 的使用方式(与许多/大多数其他功能一样)的高度多样化且通常是临时性的。