在 SQL Server 中使用正则表达式

Posted

技术标签:

【中文标题】在 SQL Server 中使用正则表达式【英文标题】:Using RegEx in SQL Server 【发布时间】:2012-02-14 05:58:56 【问题描述】:

我正在研究如何根据下面的 RegEx 设置/参数使用 RegEx 替换/编码文本:

RegEx.IgnoreCase = True     
RegEx.Global = True     
RegEx.Pattern = "[^a-z\d\s.]+"   

我在 RegEx 上看到了一些示例,但对如何在 SQL Server 中以相同的方式应用它感到困惑。任何的意见都将会有帮助。谢谢。

【问题讨论】:

您好,看看这篇文章:codeproject.com/Articles/42764/… Robyn Page and Phil Factor's 上还有一个很好的 TSQL + Windows API 解决方案,它依赖于 VBScript.RegExp 类,我相信,它已交付自 Windows 2000 以来的每个 Windows 版本。 如果您绝对需要通过 TSQL 进行 RegEx,SQL Server 2016 及更高版本的一个选项是use R services。 【参考方案1】:

您不需要与托管代码交互,因为您可以使用LIKE:

CREATE TABLE #Sample(Field varchar(50), Result varchar(50))
GO
INSERT INTO #Sample (Field, Result) VALUES ('ABC123 ', 'Do not match')
INSERT INTO #Sample (Field, Result) VALUES ('ABC123.', 'Do not match')
INSERT INTO #Sample (Field, Result) VALUES ('ABC123&', 'Match')
SELECT * FROM #Sample WHERE Field LIKE '%[^a-z0-9 .]%'
GO
DROP TABLE #Sample

当您的表达式以+ 结尾时,您可以使用'%[^a-z0-9 .][^a-z0-9 .]%'

编辑: 明确一点:SQL Server 不支持没有托管代码的正则表达式。根据具体情况,LIKE 运算符可以作为一个选项,但它缺乏正则表达式提供的灵活性。

【讨论】:

@MikeYoung,你是对的。这个答案错误地将+ 量词作为1,2 处理,而它应该将它作为1, 。令人惊讶的是,这对 OP 有效。 这在 sql server 中不起作用,因为它不支持正则表达式。 @VVN, LIKE 不是正则表达式(它是一种更受限制的模式匹配语法),因此缺少正则表达式支持并不意味着这不起作用。 @RubensFarias 根据@mike-young 的 cmets 更新答案不是很好吗?【参考方案2】:

与@mwigdahl 的回答类似,您也可以在C# 中实现一个.NET CLR,代码如下:

using System.Data.SqlTypes;
using RX = System.Text.RegularExpressions;

public partial class UserDefinedFunctions

 [Microsoft.SqlServer.Server.SqlFunction]
 public static SqlString Regex(string input, string regex)
 
  var match = RX.Regex.Match(input, regex).Groups[1].Value;
  return new SqlString (match);
 

安装说明见here

【讨论】:

【参考方案3】:

Regular Expressions In SQL Server Databases Implementation Use

正则表达式 - 描述 . 匹配任意一个字符 * 匹配任意字符 + 至少匹配 ^ 之前的表达式的一个实例 从行首开始 $ 在行尾搜索 仅当单词在此点开始时匹配 > 仅当单词在此点停止时匹配 \n 匹配换行符 [] 匹配括号内的任何字符 [^...] 匹配后面未列出的任何字符^ [ABQ]% 字符串必须以字母 A、B 或 Q 开头,并且可以是任意长度 [AB][CD]% 字符串的长度必须为 2 或以上,并且必须以 A 或 B 开头,并以 C 或 D 作为第二个字符 [AZ]% 字符串可以是任何长度,必须以 A 到 Z 的任意字母开头 [A-Z0-9]% 字符串可以是任意长度,必须以 A 到 Z 的任意字母或数字 f 开头rom 0 到 9 [^AC]% 字符串可以是任意长度,但不能以字母 A 到 C 开头 %[AZ]字符串可以是任意长度,并且必须以从 A 到 Z 的任意字母结尾 %[%$#@]% 字符串可以是任意长度,并且必须至少包含以下之一括号中的特殊字符

【讨论】:

我对这篇文章感到困惑。 SQL Server LIKE 并不支持上述所有内容。但其中一些是。这是 LIKE 表达式和标准正则表达式正则表达式的混合体吗?例如 和 ^ 和 $ 用于行的开始和结束。 @Zeek2 这个答案具有误导性。 LIKE(或PATINDEX)仅支持in the docs列出的通配符匹配,即%, [], [^], _【参考方案4】:

您必须构建一个提供正则表达式功能的 CLR 过程,如 this article 所示。

他们的示例函数使用 VB.NET:

Imports System
Imports System.Data.Sql
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlTypes
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Imports System.Collections 'the IEnumerable interface is here  


Namespace SimpleTalk.Phil.Factor
    Public Class RegularExpressionFunctions
        'RegExIsMatch function
        <SqlFunction(IsDeterministic:=True, IsPrecise:=True)> _
        Public Shared Function RegExIsMatch( _
                                            ByVal pattern As SqlString, _
                                            ByVal input As SqlString, _
                                            ByVal Options As SqlInt32) As SqlBoolean
            If (input.IsNull OrElse pattern.IsNull) Then
                Return SqlBoolean.False
            End If
            Dim RegExOption As New System.Text.RegularExpressions.RegExOptions
            RegExOption = Options
            Return RegEx.IsMatch(input.Value, pattern.Value, RegExOption)
        End Function
    End Class      ' 
End Namespace

...并使用以下 SQL 安装在 SQL Server 中(将 '%' 分隔的变量替换为它们的实际等价物:

sp_configure 'clr enabled', 1
RECONFIGURE WITH OVERRIDE

IF EXISTS ( SELECT   1
            FROM     sys.objects
            WHERE    object_id = OBJECT_ID(N'dbo.RegExIsMatch') ) 
   DROP FUNCTION dbo.RegExIsMatch
go

IF EXISTS ( SELECT   1
            FROM     sys.assemblies asms
            WHERE    asms.name = N'RegExFunction ' ) 
   DROP ASSEMBLY [RegExFunction]

CREATE ASSEMBLY RegExFunction 
           FROM '%FILE%'
GO

CREATE FUNCTION RegExIsMatch
   (
    @Pattern NVARCHAR(4000),
    @Input NVARCHAR(MAX),
    @Options int
   )
RETURNS BIT
AS EXTERNAL NAME 
   RegExFunction.[SimpleTalk.Phil.Factor.RegularExpressionFunctions].RegExIsMatch
GO

--a few tests
---Is this card a valid credit card?
SELECT dbo.RegExIsMatch ('^(?:4[0-9]12(?:[0-9]3)?|5[1-5][0-9]14|6(?:011|5[0-9][0-9])[0-9]12|3[47][0-9]13|3(?:0[0-5]|[68][0-9])[0-9]11|(?:2131|1800|35\d3)\d11)$','4241825283987487',1)
--is there a number in this string
SELECT dbo.RegExIsMatch( '\d','there is 1 thing I hate',1)
--Verifies number Returns 1
DECLARE @pattern VARCHAR(255)
SELECT @pattern ='[a-zA-Z0-9]\d2[a-zA-Z0-9](-\d3)2[A-Za-z0-9]'
SELECT  dbo.RegExIsMatch (@pattern, '1298-673-4192',1),
        dbo.RegExIsMatch (@pattern,'A08Z-931-468A',1),
        dbo.RegExIsMatch (@pattern,'[A90-123-129X',1),
        dbo.RegExIsMatch (@pattern,'12345-KKA-1230',1),
        dbo.RegExIsMatch (@pattern,'0919-2893-1256',1)

【讨论】:

这是Classic ASP,支持吗?我认为 CLR 仅适用于 .NET 函数,对吧? CLR 过程安装在 SQL Server 环境中,可以像任何其他存储过程或用户定义函数一样被调用,因此如果 Classic ASP 可以调用存储过程或用户定义函数,它可以调用一个 CLR 过程。 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review 谢谢@FedericoklezCulloca。这是一个旧答案,我已相应更新。 @mwigdahl 谢谢。我看到它很旧,但它突然出现在审查队列中:)【参考方案5】:

Julio's answer.的略微修改版

-- MS SQL using VBScript Regex
-- select dbo.RegexReplace('aa bb cc','($1) ($2) ($3)','([^\s]*)\s*([^\s]*)\s*([^\s]*)')
-- $$ dollar sign, $1 - $9 back references, $& whole match

CREATE FUNCTION [dbo].[RegexReplace]
(   -- these match exactly the parameters of RegExp
    @searchstring varchar(4000),
    @replacestring varchar(4000),
    @pattern varchar(4000)
)
RETURNS varchar(4000)
AS
BEGIN
    declare @objRegexExp int, 
        @objErrorObj int,
        @strErrorMessage varchar(255),
        @res int,
        @result varchar(4000)

    if( @searchstring is null or len(ltrim(rtrim(@searchstring))) = 0) return null
    set @result=''
    exec @res=sp_OACreate 'VBScript.RegExp', @objRegexExp out
    if( @res <> 0) return '..VBScript did not initialize'
    exec @res=sp_OASetProperty @objRegexExp, 'Pattern', @pattern
    if( @res <> 0) return '..Pattern property set failed'
    exec @res=sp_OASetProperty @objRegexExp, 'IgnoreCase', 0
    if( @res <> 0) return '..IgnoreCase option failed'
    exec @res=sp_OAMethod @objRegexExp, 'Replace', @result OUT,
         @searchstring, @replacestring
    if( @res <> 0) return '..Bad search string'
    exec @res=sp_OADestroy @objRegexExp
    return @result
END

您需要在 SQL 中打开 Ole 自动化过程:

exec sp_configure 'show advanced options',1; 
go
reconfigure; 
go
sp_configure 'Ole Automation Procedures', 1; 
go
reconfigure; 
go
sp_configure 'show advanced options',0; 
go
reconfigure;
go

【讨论】:

顺便说一句,销毁和重新创建正则表达式对象比缓存和重用它要快得多。我们进行了 10,000 次比较,重复使用该对象的次数显着增加。【参考方案6】:
SELECT * from SOME_TABLE where NAME like '%[^A-Z]%'

或其他一些表达方式,而不是 A-Z

【讨论】:

以上是关于在 SQL Server 中使用正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 中使用正则表达式检查字符串是不是为数字?

带正则表达式的参数化 SQL、ORACLE 与 SQL Server

Sql Server 使用正则表达式

SQL Server中利用正则表达式替换字符串

SQL Server:选择列中多次出现正则表达式匹配的行

使 SQL Server 中的正则表达式搜索更高效