Máy chủ SQL Biểu thức chính quy trong T-SQL


127

Có thư viện biểu thức chính quy nào được viết bằng T-SQL (không CLR, không mở rộng SP, T-SQL thuần túy) cho SQL Server không và có nên hoạt động với lưu trữ chia sẻ không?

Biên tập:

  • Cảm ơn, tôi biết về PATINDEX, LIKE, xp_ spsvà các giải pháp CLR
  • Tôi cũng biết đó không phải là nơi tốt nhất cho regex, câu hỏi chỉ là lý thuyết :)
  • Chức năng giảm cũng được chấp nhận

2
Tôi cũng có câu hỏi này. Tôi biết rằng cơ sở dữ liệu không phải là nơi tốt nhất để có thứ này, nhưng thực tế là các giải pháp khác yêu cầu quyền quản trị SQL để cấu hình lại máy chủ. Thật không may, một số khách hàng của chúng tôi sẽ không chọn bật CLR, v.v. và chúng tôi bị mắc kẹt với các giải pháp chỉ dành cho cơ sở dữ liệu.
Paul Draper

@PaulDraper và xnagyg: tại sao loại trừ SQLCLR? Đây là phương tiện thích hợp nhất để nhận Biểu thức chính quy trong các truy vấn. Và tại sao một số khách hàng của bạn chọn không bật CLR? Tôi chưa đi qua một lý do hợp lệ . Chắc chắn, tôi nghe thấy "bảo mật" và "hiệu suất", nhưng đó là những lý do không có thật là kết quả của việc không hiểu cách thức hoạt động của SQLCLR và cách nó có thể bị hạn chế.
Solomon Rutzky

3
@srutzky: hầu hết nhà cung cấp dịch vụ lưu trữ chia sẻ không cho phép CLR. Bạn nên hỏi họ về "bảo mật" và "hiệu suất" :)
xnagyg

@xnagyg Chắc chắn, tôi có thể hỏi một vài. Tuy nhiên, việc chỉ ra hành vi của một nhóm không bằng bất kỳ cách nào giải quyết câu hỏi "có lý do hợp lệ " cho hành vi đó không. Tất cả các nhà cung cấp dịch vụ lưu trữ chia sẻ này có thể dễ dàng đặt ra chính sách của họ dựa trên sự hiểu lầm tương tự. Và, nếu không có gì khác, thực tế đơn giản mà không tất cả trong số họ không cho phép SQLCLR thực sự ủng hộ ý tưởng đó không là một vấn đề hơn ý tưởng đó là một vấn đề vì nếu những vấn đề đã tồn tại, các nhà cung cấp cho phép SQLCLR sẽ được trải nghiệm những vấn đề đó và sẽ ngừng cho phép nó.
Solomon Rutzky

@xnagyg Ngoài ra, tôi nên làm rõ rằng tôi đang nói về các Hội đồng được đánh dấu SAFEvà không được đánh dấu là EXTERNAL_ACCESShoặc UNSAFE(vì tôi hiểu tại sao 2 Bộ quyền sau này sẽ gặp vấn đề đối với môi trường lưu trữ được chia sẻ). Cơ sở dữ liệu Microsoft Azure SQL V12 (tức là phiên bản mới vào cuối năm 2014), là môi trường dùng chung, cho phép các Hội đồng được đánh dấu là SAFE(và được tải qua FROM 0x...thay vì từ DLL vì bạn không thể tải lên DLL). Nhưng SAFElà tất cả những gì cần thiết cho Biểu thức chính quy và RẤT NHIỀU chức năng rất hữu ích khác.
Solomon Rutzky

Câu trả lời:


77

Làm thế nào về chức năng PATINDEX ?

Khớp mẫu trong TSQL không phải là một thư viện regex hoàn chỉnh, nhưng nó cung cấp cho bạn những điều cơ bản.

(Từ Sách trực tuyến)

Wildcard  Meaning  
% Any string of zero or more characters.

_ Any single character.

[ ] Any single character within the specified range 
    (for example, [a-f]) or set (for example, [abcdef]).

[^] Any single character not within the specified range 
    (for example, [^a - f]) or set (for example, [^abcdef]).

7
Trong ít nhất một thập kỷ (SQL Server 2005+), LIKEđã hỗ trợ mọi thứ PATINDEX. Không biết về điều đó trước đó ...
TJ Crowder

1
Tuy nhiên, điều này không cho phép tôi chỉ định một mẫu phù hợp, giả sử, một số lượng chữ cái ascii khác nhau. %khớp 0 hoặc nhiều ký tự (không phân biệt), [...]chỉ khớp một và không có gì ở giữa.
Martijn Pieters

THÍCH giống như PATINDEX> 0
Kỹ sư đảo ngược

21

Nếu bất cứ ai quan tâm đến việc sử dụng regex với CLR thì đây là một giải pháp. Hàm bên dưới (C # .net 4.5) trả về 1 nếu mẫu được khớp và 0 nếu mẫu không khớp. Tôi sử dụng nó để gắn thẻ dòng trong các truy vấn phụ. Thuộc tính SQLfunction cho máy chủ sql biết rằng phương thức này là UDF thực tế mà máy chủ SQL sẽ sử dụng. Lưu tệp dưới dạng dll ở nơi bạn có thể truy cập tệp từ studio quản lý.

// default using statements above
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;

namespace CLR_Functions
{   
    public class myFunctions
    {
        [SqlFunction]
        public static SqlInt16 RegexContain(SqlString text, SqlString pattern)
        {            
            SqlInt16 returnVal = 0;
            try
            {
                string myText = text.ToString();
                string myPattern = pattern.ToString();
                MatchCollection mc = Regex.Matches(myText, myPattern);
                if (mc.Count > 0)
                {
                    returnVal = 1;
                }
            }
            catch
            {
                returnVal = 0;
            }

            return returnVal;
        }
    }
}

Trong studio quản lý nhập tệp dll thông qua khả năng lập trình - lắp ráp - lắp ráp mới

Sau đó chạy truy vấn này:

CREATE FUNCTION RegexContain(@text NVARCHAR(50), @pattern NVARCHAR(50))
RETURNS smallint 
AS
EXTERNAL NAME CLR_Functions.[CLR_Functions.myFunctions].RegexContain

Sau đó, bạn sẽ có quyền truy cập đầy đủ vào chức năng thông qua cơ sở dữ liệu bạn đã lưu trữ lắp ráp.

Sau đó sử dụng trong các truy vấn như vậy:

SELECT * 
FROM 
(
    SELECT
        DailyLog.Date,
        DailyLog.Researcher,
        DailyLog.team,
        DailyLog.field,
        DailyLog.EntityID,
        DailyLog.[From],
        DailyLog.[To],
        dbo.RegexContain(Researcher, '[\p{L}\s]+') as 'is null values'
    FROM [DailyOps].[dbo].[DailyLog]
) AS a
WHERE a.[is null values] = 0

14

Có một số kết hợp mẫu cơ bản có sẵn thông qua việc sử dụng THÍCH, trong đó% khớp với bất kỳ số lượng và tổ hợp ký tự nào, _ khớp với bất kỳ một ký tự nào và [abc] có thể khớp với a, b hoặc c ... Có thêm thông tin trên trang web MSDN .


5

Nếu bạn đang sử dụng SQL Server 2016 trở lên, bạn có thể sử dụng sp_execute_external_scriptcùng với R. Nó có các chức năng cho các tìm kiếm Biểu thức chính quy, chẳng hạn như grepgrepl.

Đây là một ví dụ cho các địa chỉ email. Tôi sẽ truy vấn một số "người" thông qua công cụ cơ sở dữ liệu SQL Server, chuyển dữ liệu cho những người đó đến R, để R quyết định những người nào có địa chỉ email không hợp lệ và R trả lại tập hợp con người đó cho SQL Server. "Người" là từ [Application].[People]bảng trong [WideWorldImporters]cơ sở dữ liệu mẫu. Chúng được chuyển đến công cụ R dưới dạng một khung dữ liệu có tên InputDataSet. R sử dụng hàm grepl với toán tử "không" (dấu chấm than!) Để tìm những người có địa chỉ email không khớp với mẫu tìm kiếm chuỗi RegEx.

EXEC sp_execute_external_script 
 @language = N'R',
 @script = N' RegexWithR <- InputDataSet;
OutputDataSet <- RegexWithR[!grepl("([_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,4}))", RegexWithR$EmailAddress), ];',
 @input_data_1 = N'SELECT PersonID, FullName, EmailAddress FROM Application.People'
 WITH RESULT SETS (([PersonID] INT, [FullName] NVARCHAR(50), [EmailAddress] NVARCHAR(256)))

Lưu ý rằng các tính năng phù hợp phải được cài đặt trên máy chủ SQL Server. Đối với SQL Server 2016, nó được gọi là "Dịch vụ SQL Server R". Đối với SQL Server 2017, nó đã được đổi tên thành "Dịch vụ học máy SQL Server".

Kết thúc suy nghĩ Việc triển khai SQL (T-SQL) của Microsoft không có hỗ trợ riêng cho RegEx. Giải pháp đề xuất này có thể không được mong muốn hơn đối với OP so với việc sử dụng thủ tục lưu sẵn CLR. Nhưng nó cung cấp một cách bổ sung để tiếp cận vấn đề.


4

Trong trường hợp bất kỳ ai khác vẫn đang xem câu hỏi này, http://www.sqlsharp.com/ là cách miễn phí, dễ dàng để thêm các hàm CLR biểu thức chính quy vào cơ sở dữ liệu của bạn.


3
Một lần nữa, tôi là một giải pháp CLR - không phải những gì OP yêu cầu
Kỹ sư đảo ngược

10
@DaveBoltman: Anh ấy đã đặt câu hỏi vào năm 2008. Mọi người đôi khi tìm kiếm câu hỏi này và chạy qua câu hỏi này mà không muốn tránh CLR. Điều này đã giúp tôi và có thể giúp họ.
John Fisher

Chắc chắn, tôi đồng ý với bạn @JohnFisher - đó một câu trả lời hữu ích cho ai đó sử dụng CLR. Nhưng vào năm 2015, chúng tôi vẫn muốn một giải pháp duy nhất cho SQL trong dự án SQL của chúng tôi (không có CLR) vì nhiều lý do, giống như OP đã làm trong năm 2008. Năm đó không thành vấn đề :) Ví dụ: pin trong xe của bạn đã được phát hành vào 1859 . Nhưng bạn vẫn muốn tránh sử dụng các loại pin hiện đại hơn như pin NiMH được phát hành hơn 100 năm sau, vì nhiều lý do (chẳng hạn như có thể mua được xe hơi :)
Kỹ sư đảo ngược

2
@DaveBoltman: Bạn đã bỏ lỡ phần "Đôi khi mọi người tìm kiếm điều này và chạy qua câu hỏi này mà không muốn tránh CLR". Đó là điểm mấu chốt.
John Fisher

chắc chắn - bạn nói đúng @JohnFisher, bạn đã nói thế. Rất vui vì nó đã giúp bạn và tôi chắc chắn nó cũng sẽ giúp người khác
Kỹ sư đảo ngược

2

Bạn có thể sử dụng các tính năng biểu thức chính quy VBScript bằng OLE Tự động. Đây là cách tốt hơn so với chi phí tạo và duy trì lắp ráp. Vui lòng đảm bảo rằng bạn đi qua phần bình luận để có phiên bản sửa đổi tốt hơn của phiên bản chính.

http://bloss.msdn.com/b/khen1234/archive/2005/05/11/416392.aspx

DECLARE @obj INT, @res INT, @match BIT;
DECLARE @pattern varchar(255) = '<your regex pattern goes here>';
DECLARE @matchstring varchar(8000) = '<string to search goes here>';
SET @match = 0;

-- Create a VB script component object
EXEC @res = sp_OACreate 'VBScript.RegExp', @obj OUT;

-- Apply/set the pattern to the RegEx object
EXEC @res = sp_OASetProperty @obj, 'Pattern', @pattern;

-- Set any other settings/properties here
EXEC @res = sp_OASetProperty @obj, 'IgnoreCase', 1;

-- Call the method 'Test' to find a match
EXEC @res = sp_OAMethod @obj, 'Test', @match OUT, @matchstring;

-- Don't forget to clean-up
EXEC @res = sp_OADestroy @obj;

Nếu bạn gặp SQL Server blocked access to procedure 'sys.sp_OACreate'...lỗi, sử dụng sp_reconfiguređể kích hoạt Ole Automation Procedures. (Vâng, thật không may, đó là một sự thay đổi cấp độ máy chủ!)

Thông tin thêm về Testphương pháp có sẵn ở đây

Chúc mừng mã hóa


Xin lỗi, tôi biết điều này đã cũ, NHƯNG: Tại sao VBScript thông qua OLE "tốt hơn" so với CLR? Nếu bạn CHỈ nghĩ về bảo trì, bạn CÓ THỂ đúng, NHƯNG điều gì về hiệu suất?
swe

1
@swe Bằng cách 'tốt hơn', tôi đã đề cập đến thời gian tiết kiệm được do chi phí tạo và duy trì lắp ráp .NET chỉ cho mục đích này.
James Poulose
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.