ใช้ 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ที่ดีที่Robyn Page และ Phil Factorซึ่งอาศัยคลาสVBScript.RegExpซึ่งฉันเชื่อว่ามีการจัดส่งใน Windows ทุกเวอร์ชันตั้งแต่ Windows 2000
Julio Nobre

ถ้าคุณอย่างต้องบวก RegEx ผ่าน TSQL ตัวเลือกสำหรับ SQL Server 2016 และข้างต้นคือการใช้บริการ R
Dave Mason

คำตอบ:


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

2
สิ่งนี้จะไม่ทำงานในเซิร์ฟเวอร์ sql เนื่องจากไม่รองรับ regex
VVN

10
@VVN LIKEไม่ใช่ regex (เป็นไวยากรณ์การจับคู่รูปแบบที่ จำกัด มากขึ้น) ดังนั้นการขาดการสนับสนุน regex ไม่ได้หมายความว่าจะใช้ไม่ได้
Charles Duffy

@RubensFarias จะไม่เป็นการดีที่จะอัปเดตคำตอบในแง่ของความคิดเห็นจาก @ mike-young?
Sudhanshu Mishra

8

คำตอบของ 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

คุณจะต้องเปิด Ole Automation Procedures ใน 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
BTW สามารถทำลายและสร้างวัตถุ regex ได้เร็วกว่าการแคชและนำมาใช้ใหม่ เราทำการเปรียบเทียบ 10,000 ครั้งโดยมีตัวเลขที่สูงกว่าอย่างมีนัยสำคัญโดยใช้วัตถุซ้ำ
Zachary Scott

8

คุณจะต้องสร้างโพรซีเดอร์ CLR ที่ให้ฟังก์ชัน regex ดังที่แสดงในบทความนี้

ฟังก์ชันตัวอย่างของพวกเขาใช้ 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 และสามารถเรียกใช้เหมือนกับโพรซีเดอร์ที่จัดเก็บอื่น ๆ หรือฟังก์ชันที่ผู้ใช้กำหนดดังนั้นหาก Classic ASP สามารถเรียกใช้โพรซีเดอร์ที่เก็บไว้หรือฟังก์ชันที่ผู้ใช้กำหนดเองก็สามารถเรียกใช้โพรซีเดอร์ CLR ได้
mwigdahl

1
แม้ว่าลิงก์นี้อาจตอบคำถามได้ แต่ควรรวมส่วนสำคัญของคำตอบไว้ที่นี่และระบุลิงก์เพื่อการอ้างอิง คำตอบแบบลิงก์เท่านั้นอาจไม่ถูกต้องหากหน้าที่เชื่อมโยงเปลี่ยนไป - จากรีวิว
Federico klez Culloca

ขอบคุณ @FedericoklezCulloca นี่เป็นคำตอบเก่าและฉันได้อัปเดตตามนั้น
mwigdahl

@mwigdahl ขอบคุณสำหรับสิ่งนั้น ฉันเห็นว่ามันเก่า แต่มันโผล่ขึ้นมาในคิวการตรวจสอบ :)
Federico klez Culloca

7

นิพจน์ทั่วไปในการใช้งานฐานข้อมูล SQL Server

นิพจน์ปกติ -
คำอธิบาย จับคู่อักขระใดตัวหนึ่ง
* จับคู่อักขระใด ๆ
+ จับคู่นิพจน์อย่างน้อยหนึ่งอินสแตนซ์ก่อน
^ เริ่มต้นที่จุดเริ่มต้นของบรรทัด
$ ค้นหาที่ท้ายบรรทัด
< จับคู่เฉพาะเมื่อคำขึ้นต้นที่จุดนี้
> จับคู่เฉพาะเมื่อคำหยุดที่จุดนี้
\ n จับคู่ตัวแบ่งบรรทัด
[] จับคู่อักขระใด ๆ ภายในวงเล็บ
[^ ... ] จับคู่อักขระใด ๆ ที่ไม่อยู่หลัง ^
[ABQ]% สตริงต้องขึ้นต้นด้วยตัวอักษร A, B หรือ Q และสามารถมีความยาวเท่าใดก็ได้
[เอบีซีดี]% สตริงต้องมีความยาวตั้งแต่สองตัวขึ้นไปและต้องขึ้นต้นด้วย A หรือ B และมี C หรือ D เป็นอักขระตัวที่สอง
[AZ]% สตริงจะมีความยาวเท่าใดก็ได้และต้องขึ้นต้นด้วยตัวอักษรใดก็ได้ตั้งแต่ A ถึง Z
[A -Z0-9]% สตริงสามารถมีความยาวเท่าใดก็ได้และต้องขึ้นต้นด้วยตัวอักษร A ถึง Z หรือตัวเลขตั้งแต่ 0 ถึง 9
[^ AC]%สตริงสามารถมีความยาวเท่าใดก็ได้ แต่ไม่สามารถขึ้นต้นด้วยตัวอักษร A ถึง C
% [AZ] สตริงสามารถมีความยาวเท่าใดก็ได้และต้องลงท้ายด้วยตัวอักษรใดก็ได้ตั้งแต่ 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);
 }
}

คำแนะนำในการติดตั้งสามารถพบได้ที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.