Использование RegEx в SQL Server

94

Я ищу, как заменить / закодировать текст с помощью RegEx на основе настроек / параметров RegEx ниже:

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

Я видел несколько примеров с RegEx, но не понимал, как применить его таким же образом в SQL Server. Любые предложения будут полезны. Спасибо.

Урод контроль
источник
1
Привет, взгляните на эту статью: codeproject.com/Articles/42764/…
Mohsen
Также у Робина Пейджа и Фила Фактора есть отличное решение TSQL + Windows API , которое опирается на класс VBScript.RegExp , который, как я полагаю, входит в каждую версию Windows, начиная с Windows 2000.
Хулио Нобре
Если вы абсолютно положительно необходимо RegEx через TSQL, вариант для SQL Server 2016 и выше к услугам использование R .
Дэйв Мейсон

Ответы:

105

Вам не нужно взаимодействовать с управляемым кодом, так как вы можете использовать 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оператор может быть вариантом, но ему не хватает гибкости, которую обеспечивают регулярные выражения.

Рубенс Фариас
источник
8
@MikeYoung, ты прав. Этот ответ неверно относится к +квантификатору, {1,2}когда он должен его принимать как {1, }. Удивительно, но это сработало с OP.
Рубенс Фариас
2
Это не будет работать на сервере sql, поскольку оно не поддерживает регулярное выражение.
VVN
10
@VVN LIKEне является регулярным выражением (это более ограниченный синтаксис сопоставления с образцом), поэтому отсутствие поддержки регулярных выражений не означает, что это не сработает.
Чарльз Даффи
@RubensFarias, было бы неплохо обновить ответ в свете комментариев @ mike-young?
Судханшу Мишра
8

Немного измененная версия ответа Хулио.

-- 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

Вам понадобится включить процедуры Ole Automation в SQL:

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
Закари Скотт
источник
2
Кстати, гораздо быстрее уничтожить и воссоздать объект регулярного выражения, чем кэшировать и повторно использовать его. Мы провели 10 000 сравнений со значительно более высокими значениями повторного использования объекта.
Zachary Scott
8

Вам нужно будет создать процедуру CLR, которая обеспечивает функциональность регулярного выражения, как показано в этой статье .

Их примерная функция использует 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 Server с использованием следующего SQL (замена переменных с разделителями "%" их фактическими эквивалентами:

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\d{3})\d{11})$','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]\d{2}[a-zA-Z0-9](-\d{3}){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, верно?
Control Freak
4
Процедуры CLR устанавливаются в среду SQL Server и могут быть вызваны так же, как любая другая хранимая процедура или определяемая пользователем функция, поэтому, если классический ASP может вызывать хранимую процедуру или определяемую пользователем функцию, он может вызывать процедуру CLR.
mwigdahl
1
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из
отзыва
Спасибо @FedericoklezCulloca. Это был старый ответ, и я его соответствующим образом обновил.
mwigdahl
@mwigdahl, спасибо за это. Я вижу, он старый, но он появился в очереди на просмотр :)
Федерико Клез Каллока
7

Регулярные выражения в использовании реализации баз данных SQL Server

Регулярное выражение - Описание
. Соответствует любому символу
* Соответствует любому символу
+ Соответствует хотя бы одному экземпляру выражения перед
^ Начать в начале строки
$ Искать в конце строки
< Сопоставлять, только если слово начинается в этой точке
> Сопоставлять, только если слово останавливается в этой точке
\ n Соответствует разрыву строки
[] Соответствует любому символу в квадратных скобках
[^ ...] Соответствует любому символу, не указанному после ^
[ABQ]% Строка должна начинаться с букв A, B или Q и может иметь любую длину
[AB] [CD]% Строка должна иметь длину два или более и начинаться с A или B и содержать C или D в качестве второго символа
[AZ]% Строка может быть любой длины и должна начинаться с любой буквы от A до Z
[A -Z0-9]% Строка может быть любой длины и должна начинаться с любой буквы от A до Z или цифры от 0 до 9
[^ AC]% Строка может быть любой длины, но не может начинаться с букв от A до C
% [AZ] Строка может быть любой длины и должна заканчиваться любой из букв от A до Z
% [% $ # @]% Строка может быть любой длины и должна содержать хотя бы один из специальных символов, заключенных в скоба

Рави Маквана
источник
5
SELECT * from SOME_TABLE where NAME like '%[^A-Z]%'

Или какое-нибудь другое выражение вместо АЗ

Калян Васантх
источник
1

Подобно ответу @mwigdahl, вы также можете реализовать .NET CLR на C # с таким кодом, как;

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);
 }
}

Инструкцию по установке можно найти здесь

Фиах Рид
источник