Utilizzo di RegEx in SQL Server


92

Sto cercando di sostituire / codificare il testo utilizzando RegEx in base alle impostazioni / parametri RegEx di seguito:

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

Ho visto alcuni esempi su RegEx, ma sono confuso su come applicarlo allo stesso modo in SQL Server. Eventuali suggerimenti sarebbero utili. Grazie.


1
Ciao, dai un'occhiata a questo articolo: codeproject.com/Articles/42764/…
Mohsen

C'è anche una buona soluzione TSQL + API Windows su Robyn Page e Phil Factor che si basa sulla classe VBScript.RegExp , che, credo, viene fornita su ogni versione di Windows da Windows 2000.
Julio Nobre

Se è assolutamente necessario positivamente RegEx via TSQL, un'opzione per SQL Server 2016 e in precedenza è quello di utilizzare servizi R .
Dave Mason

Risposte:


103

Non è necessario interagire con il codice gestito, poiché è possibile utilizzare 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

Quando la tua espressione finisce con +puoi andare con'%[^a-z0-9 .][^a-z0-9 .]%'

EDIT : per chiarire: SQL Server non supporta le espressioni regolari senza codice gestito. A seconda della situazione, l' LIKEoperatore può essere un'opzione, ma manca della flessibilità fornita dalle espressioni regolari.


8
@MikeYoung, hai ragione. Questa risposta indirizza erroneamente il +quantificatore come {1,2}quando dovrebbe prenderlo come {1, }. Sorprendentemente, questo ha funzionato per l'OP.
Rubens Farias

2
Questo non funziona nel server sql poiché non supporta regex.
VVN

10
@VVN, LIKEnon è regex (è una sintassi di corrispondenza dei modelli più limitata), quindi la mancanza di supporto per regex non significa che questo non funzionerà.
Charles Duffy

@RubensFarias non sarebbe bello aggiornare la risposta alla luce dei commenti di @ mike-young?
Sudhanshu Mishra

8

Versione leggermente modificata della risposta di Julio.

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

Avrai bisogno di Ole Automation Procedure attivate in 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
A proposito, è molto più veloce distruggere e ricreare l'oggetto regex che metterlo in cache e riutilizzarlo. Abbiamo eseguito 10.000 confronti con numeri significativamente più alti riutilizzando l'oggetto.
Zachary Scott

8

Dovrai creare una procedura CLR che fornisca funzionalità regex, come illustrato in questo articolo .

La loro funzione di esempio utilizza 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

... ed è installato in SQL Server utilizzando il seguente SQL (sostituendo '%' - variabili delimitate dai loro equivalenti effettivi:

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)

Questo è in Classic ASP, supporta? Penso che CLR sia solo per le funzioni .NET, giusto?
Control Freak

4
Le procedure CLR vengono installate nell'ambiente SQL Server e possono essere richiamate come qualsiasi altra stored procedure o funzione definita dall'utente, quindi se Classic ASP può richiamare una stored procedure o una funzione definita dall'utente, può richiamare una procedura CLR.
mwigdahl

1
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere le parti essenziali della risposta qui e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
Federico klez Culloca

Grazie @FedericoklezCulloca. Questa era una vecchia risposta e l'ho aggiornata di conseguenza.
mwigdahl

@mwigdahl, grazie per questo. Vedo che è vecchio, ma è saltato fuori in una coda di recensioni :)
Federico klez Culloca

7

Espressioni regolari nell'implementazione dei database di SQL Server

Espressione regolare - Descrizione
. Trova un carattere qualsiasi
* Trova qualsiasi carattere
+ Trova almeno un'istanza dell'espressione prima di
^ Inizia all'inizio della riga
$ Cerca alla fine della riga
< Trova la corrispondenza solo se la parola inizia a questo punto
> Trova la corrispondenza solo se la parola si ferma a questo punto
\ n Trova una interruzione di riga
[] Trova qualsiasi carattere tra parentesi
[^ ... ] Trova qualsiasi carattere non elencato dopo ^
[ABQ]% La stringa deve iniziare con le lettere A, B o Q e può essere di qualsiasi lunghezza
[AB] [CD]% La stringa deve avere una lunghezza di due o più e deve iniziare con A o B e avere C o D come secondo carattere
[AZ]% La stringa può essere di qualsiasi lunghezza e deve iniziare con qualsiasi lettera dalla A alla Z
[A -Z0-9]% La stringa può essere di qualsiasi lunghezza e deve iniziare con qualsiasi lettera dalla A alla Z o un numero da 0 a 9
[^ AC]% La stringa può essere di qualsiasi lunghezza ma non può iniziare con le lettere dalla A alla C
% [AZ] La stringa può essere di qualsiasi lunghezza e deve terminare con una qualsiasi delle lettere dalla A alla Z
% [% $ # @]% La stringa può essere di qualsiasi lunghezza e deve contenere almeno uno dei caratteri speciali racchiusi tra la staffa


5
SELECT * from SOME_TABLE where NAME like '%[^A-Z]%'

O qualche altra espressione invece di AZ


1

Un approccio simile alla risposta di @ mwigdahl, puoi anche implementare un .NET CLR in C #, con codice come;

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

Le istruzioni di installazione possono essere trovate qui

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.