Menggunakan RegEx di SQL Server

94

Saya mencari cara mengganti / menyandikan teks menggunakan RegEx berdasarkan pengaturan / parameter RegEx di bawah ini:

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

Saya telah melihat beberapa contoh di RegEx, tetapi bingung bagaimana cara menerapkannya dengan cara yang sama di SQL Server. Setiap saran akan membantu. Terima kasih.

Gila kontrol
sumber
1
Hai, lihat artikel ini: codeproject.com/Articles/42764/…
Mohsen
Ada juga solusi TSQL + Windows API yang bagus di Robyn Page dan Phil Factor yang bergantung pada VBScript. Kelas RegExp, yang, saya percaya, dikirimkan pada setiap versi Windows sejak Windows 2000.
Julio Nobre
Jika Anda benar-benar butuh regex melalui TSQL, pilihan untuk SQL Server 2016 dan di atas adalah untuk menggunakan layanan R .
Dave Mason

Jawaban:

105

Anda tidak perlu berinteraksi dengan kode terkelola, karena Anda dapat menggunakan 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

Saat ekspresi Anda berakhir, +Anda bisa pergi dengan'%[^a-z0-9 .][^a-z0-9 .]%'

EDIT : untuk memperjelas: SQL Server tidak mendukung ekspresi reguler tanpa kode yang dikelola. Bergantung pada situasinya, LIKEoperator dapat menjadi opsi, tetapi tidak memiliki fleksibilitas yang disediakan ekspresi reguler.

Rubens Farias
sumber
8
@MikeYoung, kamu benar. Jawaban ini salah membahas +pembilang sebagaimana {1,2}mestinya {1, }. Anehnya, ini berhasil ke OP.
Rubens Farias
2
Ini tidak akan berfungsi di server sql karena tidak mendukung regex.
VVN
10
@VVN, LIKEbukan regex (ini adalah sintaks pencocokan pola yang lebih terbatas), jadi kurangnya dukungan regex tidak berarti bahwa ini tidak akan berfungsi.
Charles Duffy
@RubensFarias Bukankah menyenangkan untuk memperbarui jawaban sehubungan dengan komentar dari @ mike-young?
Sudhanshu Mishra
8

Versi jawaban Julio yang sedikit dimodifikasi .

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

Anda perlu mengaktifkan Prosedur Otomasi Ole di 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
Zachary Scott
sumber
2
BTW, jauh lebih cepat menghancurkan dan membuat ulang objek regex daripada meng-cache dan menggunakannya kembali. Kami menjalankan 10.000 perbandingan dengan jumlah yang jauh lebih tinggi menggunakan kembali objek tersebut.
Zachary Scott
8

Anda harus membuat prosedur CLR yang menyediakan fungsionalitas regex, seperti yang diilustrasikan dalam artikel ini .

Fungsi contoh mereka menggunakan 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

... dan diinstal di SQL Server menggunakan SQL berikut (menggantikan '%' - variabel yang dipisahkan dengan padanan sebenarnya:

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)
mwigdahl.dll
sumber
Ini ada di ASP Klasik, apakah itu mendukung? Saya pikir CLR hanya untuk fungsi NET, bukan?
Control Freak
4
Prosedur CLR diinstal ke dalam lingkungan SQL Server dan dapat dipanggil seperti prosedur tersimpan lainnya atau fungsi yang ditentukan pengguna, jadi jika ASP Klasik dapat menjalankan prosedur tersimpan atau fungsi yang ditentukan pengguna, ia dapat menjalankan prosedur CLR.
mwigdahl
1
Meskipun tautan ini mungkin menjawab pertanyaan, lebih baik menyertakan bagian penting dari jawaban di sini dan menyediakan tautan untuk referensi. Jawaban link saja bisa menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Federico klez Culloca
Terima kasih @FedericoklezCulloca. Ini adalah jawaban lama dan saya telah memperbaruinya.
mwigdahl
@mwigdahl terima kasih untuk itu. Saya melihat ini sudah tua, tetapi muncul dalam antrean ulasan :)
Federico klez Culloca
7

Ekspresi Reguler Dalam Penggunaan Implementasi Basis Data SQL Server

Ekspresi Reguler - Deskripsi
. Cocok dengan salah satu karakter
* Cocok dengan karakter apa pun
+ Cocokkan setidaknya satu kemunculan ekspresi sebelumnya
^ Mulai di awal baris
$ Telusuri di akhir baris
< Cocokkan hanya jika kata dimulai pada titik ini
> Cocokkan hanya jika kata berhenti di titik ini
\ n Cocokkan pemisah baris
[] Cocok dengan karakter apa pun dalam tanda kurung
[^ ...] Cocok dengan semua karakter yang tidak terdaftar setelah ^
[ABQ]% String harus dimulai dengan huruf A, B, atau Q dan dapat dengan panjang berapa pun
[AB] [CD]% String harus memiliki panjang dua atau lebih dan yang harus dimulai dengan A atau B dan memiliki C atau D sebagai karakter kedua
[AZ]% String dapat memiliki panjang berapa pun dan harus dimulai dengan huruf apa pun dari A hingga Z
[A -Z0-9]% String dapat dengan panjang berapa pun dan harus dimulai dengan huruf apa pun dari A hingga Z atau angka dari 0 hingga 9
[^ AC]% String dapat memiliki panjang berapa pun tetapi tidak dapat dimulai dengan huruf A hingga C
% [AZ] String dapat dengan panjang berapa pun dan harus diakhiri dengan salah satu huruf dari A hingga Z
% [% $ # @]% String dapat dengan panjang berapa pun dan harus berisi setidaknya salah satu karakter khusus yang diapit oleh braket

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

Atau ekspresi lain selain AZ

Kalyan Vasanth
sumber
1

Pendekatan yang mirip dengan jawaban @ mwigdahl, Anda juga dapat menerapkan CLR .NET di C #, dengan kode seperti;

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

Petunjuk penginstalan dapat ditemukan di sini

Fiach Reid
sumber