Використання RegEx в SQL Server


92

Я шукаю, як замінити / кодувати текст за допомогою RegEx на основі налаштувань / параметрів RegEx нижче:

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

Я бачив кілька прикладів на RegEx, але збентежений щодо того, як застосовувати його таким же чином у SQL Server. Будь-які пропозиції були б корисними. Дякую.


1
Привіт, погляньте на цю статтю: codeproject.com/Articles/42764/…
Мохсен,

У Robyn Page та Phil Factor 's також є прекрасне рішення API API TSQL + Windows , яке покладається на клас VBScript.RegExp , який, я вважаю, поставляється в кожній версії Windows з Windows 2000.
Хуліо Нобре

Якщо вам абсолютно необхідний RegEx через TSQL, варіантом для SQL Server 2016 і вище є використання R-служб .
Дейв Мейсон,

Відповіді:


103

Вам не потрібно взаємодіяти з керованим кодом, оскільки ви можете використовувати 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 .]%'

EDIT : щоб було зрозуміло: SQL Server не підтримує регулярні вирази без керованого коду. Залежно від ситуації LIKEоператор може бути опцією, але йому не вистачає гнучкості, яку надають регулярні вирази.


8
@MikeYoung, ти маєш рацію. Ця відповідь неправильно звертається до +квантора, як {1,2}коли він повинен його прийняти як {1, }. На диво, це спрацювало для ОП.
Рубенс Фаріас,

2
Це не працює на SQL-сервері, оскільки він не підтримує регулярний вираз.
ВВН

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 у 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 порівнянь із значно більшим числом повторного використання об’єкта.
Захарі Скотт,

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)

Це в класичному ASP, чи підтримує? Я думаю, CLR призначений лише для функцій .NET, так?
Control Freak

4
Процедури CLR встановлюються у середовище SQL Server і можуть бути викликані як будь-яка інша збережена процедура або визначена користувачем функція, тому, якщо класичний ASP може викликати збережену процедуру або визначену користувачем функцію, він може викликати процедуру CLR.
mwigdahl

1
Хоча це посилання може відповісти на питання, краще включити сюди основні частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
Federico klez Culloca

Дякую @FedericoklezCulloca. Це була стара відповідь, і я відповідно її оновив.
mwigdahl

@mwigdahl дякую за це. Я бачу, що він старий, але він з’явився в черзі оглядів :)
Федеріко Клез Куллока

7

Регулярні вирази в реалізації баз даних SQL Server

Регулярний вираз - Опис
. Зіставити будь-який один символ
* Зіставити будь-який символ
+ Зіставити принаймні один екземпляр виразу до
^ Почати на початку рядка
$ Пошук у кінці рядка
< Збіг, лише якщо слово починається з цієї точки
> Збіг, лише якщо слово зупиняється в цій точці
\ n Зіставити розрив рядка
[] Зіставити будь-який символ у дужках
[^ ...] Відповідає будь-якому символу, не вказаному після ^
[ABQ]% Рядок повинен починатися з літер A, B або Q і може мати будь-яку довжину
[А Б В Г]% Рядок повинен мати довжину дві або більше, і він повинен починатися з A або B, а C або D - другий символ
[AZ]% Рядок може мати будь-яку довжину і повинен починатися з будь-якої літери від A до Z
[A -Z0-9]% Рядок може бути будь-якої довжини і повинен починатися з будь-якої літери від А до Я або цифри від 0 до 9
[^ AC]% Рядок може бути будь-якої довжини, але не може починатися з букв А до С
% [AZ] Рядок може бути будь-якої довжини і повинен закінчуватися будь-якою літерою від А до Я
% [% $ # @]% Рядок може бути будь-якої довжини і повинен містити принаймні один із спеціальних символів, укладених у кронштейн



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

Інструкції з монтажу можна знайти тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.