1. 程式人生 > >正則表示式 第六篇:呼叫CLR函式執行正則查詢

正則表示式 第六篇:呼叫CLR函式執行正則查詢

正則表示式在文字查詢方面,不管是速度還是功能,都十分強大。雖然SQL Server資料庫可以執行模糊查詢(像like子句)和全文查詢(Fulltext search),但是這兩個子句只能查詢簡單的模式,無法應對複雜的查詢需求。這是因為SQL Server沒有執行正則表示式的內建函式,無法直接執行正則查詢。我們可以建立CLR標量函式,在函式中呼叫正則表示式,把CLR函式釋出到SQL Server資料庫中,這樣,就可以通過TSQL指令碼呼叫CLR函式來執行復雜的正則查詢和匹配。

一,Regex類

Regex類用於表示一個正則表示式,執行匹配、替換和拆分操作,Regex類有五大方法:

  • IsMatch():是否匹配到正則
  • Match():返回正則的第一個匹配
  • Matches():返回正則的全部匹配
  • Replace():把匹配正則表示式的文字替換掉
  • Split():把輸入文字拆分,拆分的邊界是匹配正則表示式的文字

1,建立Regex 物件

建立Regex物件,並指定正則選項(忽略大小寫):

Regex re = new Regex("(?<=\"UserID\":\").*?(?=\")", RegexOptions.IgnoreCase);
string mat = re.Match(input_text).Value;

也可以直接使用靜態方法,直接獲取到第一個匹配的值:

string mat = Regex.Match(input_txt,"(?<=\"UserID\":\").*?(?=\")", RegexOptions.IgnoreCase).Value;

2,查詢匹配

按照正則來檢視匹配的文字是正則表示式最常用的功能,

Regex re = new Regex("(?<=\"UserID\":\").*?(?=\")", RegexOptions.IgnoreCase);

MatchCollection mc = re.Matches(text_input);
foreach(Match mt in mc)
{
    //mt.Value
}

二,建立CLR工程

我使用的IDE版本是VS2017 Enterprise,要建立CLR工程,首先需要建立SQL Server 型別的 Project。

1,新建CLR函式

在已建立的SQL Server Project中新增新專案(Add -> New Item),選項SQL CLR C# User Defined Function,這裡把檔案命名為UserDefinedFunctions.cs。

 

2,編寫CLR程式碼

完整的CLR標量函式示例程式碼如下,Build 該檔案,生成DLL檔案,用該DLL檔案建立程式集。

為了使用正則表示式,需要在檔案中新增引用 : using System.Text.RegularExpressions;

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text;
using System.Text.RegularExpressions;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlString Match(string input, string pattern)
    {
        string str = Regex.Match(input, pattern, RegexOptions.IgnoreCase).Value;
        return new SqlString (str);
    }

    public static SqlBoolean IsMatch(string input, string pattern)
    {
        bool match = Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
        return new SqlBoolean(match);
    }

    public static SqlString Matches(string input, string pattern)
    {
        MatchCollection mc = Regex.Matches(input, pattern, RegexOptions.IgnoreCase);
        StringBuilder strList = new StringBuilder();
        int idx = 0;
        foreach(Match m in mc)
        {
            strList.Append(string.Format("\"idx{0}\":\"{1}\",", idx, m.Value));
            idx = idx + 1;
        }
        return new SqlString(strList.ToString());
    }

    public static SqlString SplitItem(string input, string separator, int idx)
    {
        string[] str = input.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries);
        return str.Length> idx ? str[idx] : "";
    }
    public static string GetJsonItem(string input, string key)
    {
        string pattern = string.Format("(?<=\"{0}\":\").*?(?=\")", key);
        return Regex.Match(input, pattern, RegexOptions.IgnoreCase).Value;
    }
}

三,在SQL Server中建立CLR函式

要在SQL Server資料庫中建立CLR函式,必須配置SQL Server的選項,然後使用DLL檔案建立Assembly,並從Assembly建立SQL 函式。

1,配置SQL Server的選項

為了把CLR工程部署到SQL Server資料庫中,需要配置資料庫的高階選項,主要是禁用clr strict security 和啟用clr enabled選項。

exec sp_configure 'show advanced options', 1 
go
reconfigure; 
go
exec sp_configure 'clr strict security', 0; 
go
reconfigure;
go
exec sp_configure 'clr enabled', 1
go
reconfigure
go

2,建立程式集

引用CLR Project生成的DLL檔案,用該DLL檔案來建立SQL Server程式集:

CREATE ASSEMBLY [SQLServerDatabase]
FROM 'E:\clr_project_path.dll'
WITH PERMISSION_SET = SAFE
GO

3,從程式集中建立SQL函式

把SQL Server Database Project中的建立的函式,逐個建立為SQL函式。

CREATE FUNCTION [dbo].[Match](@input [nvarchar](max), @pattern [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SQLServerDatabase].[UserDefinedFunctions].[Match]
GO

CREATE FUNCTION [dbo].[IsMatch](@input [nvarchar](max), @pattern [nvarchar](max))
RETURNS bit WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SQLServerDatabase].[UserDefinedFunctions].[IsMatch]
GO

CREATE FUNCTION [dbo].[Matches](@input [nvarchar](max), @pattern [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SQLServerDatabase].[UserDefinedFunctions].[Matches]
GO

CREATE FUNCTION [dbo].[SplitItem](@input [nvarchar](max), @separator [nvarchar](max), @idx int)
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SQLServerDatabase].[UserDefinedFunctions].[SplitItem]
GO

CREATE FUNCTION [dbo].[GetJsonItem](@input [nvarchar](max), @key [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SQLServerDatabase].[UserDefinedFunctions].[GetJsonItem]
GO

在SQL函式建立之後,就可以像呼叫普通函式那樣來呼叫CLR函式。

update [dbo].[DimProductPath]
set  ProductPath_ProductFamily=dbo.SplitItem(ProductPath,'/',0)
    ,ProductPath_ProductName=dbo.SplitItem(ProductPath,'/',1)
    ,ProductPath_ProductVersion=dbo.SplitItem(ProductPath,'/',2)
    ,ProductPath_SupportTopic=dbo.SplitItem(ProductPath,'/',3)
    ,ProductPath_SupportSubtopic=dbo.SplitItem(ProductPath,'/',4)

 

參考文件:

C#中正則表示式的使用

C# 正則表示式 菜鳥教程

Regular Expression Language - Quick Refer