您还可以使用此 CLR 代码在 SQL Server 中使用真正的正则表达式
参见代码,添加到 SQL Server 实例中的函数的 SQL 语句
using System;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;
using System.Collections;
using System.Data.SqlTypes;
namespace XXX.DotNet.XXX
{
/// <summary>
/// Cette classe est utilisée pour mettre à disposition une librairie de fonctions d'Expressions Régulières destinées pour SQL Server 2005 (et plus) en CLR
/// </summary>
public class RegularExpressionFunctions
{
/**
<summary>
Cette méthode permet de récupérer toutes les sous-chaines d'une chaine correspondant à une expression régulière (sous forme de chaine concaténée)
</summary>
<param name="pattern">
Cette chaîne de caractères représente l'expression régulière à comparer
</param>
<param name="sentence">
Cette chaîne de caractères représente l'expression à évaluer
</param>
<param name="separator">
Cette chaîne de caractères sera insérée entre chaque sous-chaîne
</param>
<returns>
Soit null si aucune sous-chaine ne correspond, soit une chaine correspondant à la concaténation des différentes sous-chaînes séparées par une chaîne de séparation
</returns>
*/
[SqlFunction(IsDeterministic = true, IsPrecise = true, Name = "RegExMatches")]
public static String RegExMatches(String pattern, String sentence, String separator)
{
Regex rgx = new Regex(pattern);
MatchCollection matches = rgx.Matches(sentence);
int nbFound = matches.Count;
if(nbFound == 0){return null;}// Retourne null si aucune sous-chaîne ne correspond à l'expression régulière
String toReturn = "";
for(int i = 0; i < nbFound; i++)
{
Match match = matches[i];
if(i != 0)
{
toReturn += separator;
}
toReturn += match.Value;
}
return toReturn;// Retourne les sous-chaînes séparées par la chaîne de séparation
}
/**
<summary>
Cette méthode permet de récupérer toutes les sous-chaines d'une chaine correspondant à une expression régulière (sous forme de tableau)
</summary>
<param name="pattern">
Cette chaîne de caractères représente l'expression régulière à comparer
</param>
<param name="sentence">
Cette chaîne de caractères représente l'expression à évaluer
</param>
<returns>
Un tableau de taille égale au nombre de sous-chaîne trouvées, contenant dans chaque case une sous-chaîne correspondant à l'expression régulière
</returns>
*/
[SqlFunction(Name = "RegExMatchesSplit", FillRowMethodName = "NextSplitRow", DataAccess = DataAccessKind.Read)]
public static IEnumerable RegExMatchesSplit(String pattern, String sentence)
{
Regex rgx = new Regex(pattern);
MatchCollection matches = rgx.Matches(sentence);
int nbFound = matches.Count;
//String[][] toReturn = new String[nbFound][];
String[] toReturn = new String[nbFound];
for(int i = 0; i < nbFound; i++)
{
/*toReturn[i] = new String[2];
toReturn[i][0] = sentence;
toReturn[i][1] = matches[i].Value;*/
toReturn[i] = matches[i].Value;
}
return toReturn;// Retourne les sous-chaînes dans un tableau
}
public static void NextSplitRow(Object obj, /*out SqlString sentence, */out SqlString match)
{
/*String[] row = (String[])obj;
sentence = new SqlString(row[0]);
match = new SqlString(row[1]);*/
match = new SqlString(obj.ToString());
}
/**
<summary>
Cette méthode permet de récupérer le nombre de sous-chaînes d'une chaîne correspondant à une expression régulière
</summary>
<param name="pattern">
Cette chaîne de caractères représente l'expression régulière à comparer
</param>
<param name="sentence">
Cette chaîne de caractères représente l'expression à évaluer
</param>
<returns>
Le nombre d'occurences des sous-chaînes trouvée par l'expression régulière dans la chaîne d'entrée
</returns>
*/
[SqlFunction(IsDeterministic = true, IsPrecise = true, Name = "RegExNbMatches")]
public static int RegExNbMatches(String pattern, String sentence)
{
return new Regex(pattern).Matches(sentence).Count;// Retourne le nombre de sous-chaînes trouvées
}
/**
<summary>
Cette méthode permet de savoir si une chaîne de caractère correspond à un pattern d'expression régulière
</summary>
<param name="pattern">
Cette chaîne de caractères représente l'expression régulière à comparer
</param>
<param name="sentence">
Cette chaîne de caractères représente l'expression à évaluer
</param>
<returns>
True si l'expression correspond bien au pattern, false dans le cas contraire
</returns>
*/
[SqlFunction(IsDeterministic = true, IsPrecise = true, Name = "RegExIsMatch")]
public static bool RegExIsMatch(String pattern, String sentence)
{
return new Regex(pattern).IsMatch(sentence);
}
/**
TODO - Documentation
*/
[SqlFunction(IsDeterministic = true, IsPrecise = true, Name = "RegExMatch")]
public static String RegExMatch(String pattern, String sentence)
{
Match match = new Regex(pattern).Match(sentence);
if(!match.Success){return null;}
return match.Value;
}
}
}
使用 Framework 3.5 编译以下命令可以提供帮助
"C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe" /t:library RegularExpressionFunctions.cs
编译后,将DLL放入C:\CLR\Regex\
(或其他地方并根据以下 SQL Query 更改)
然后使用以下代码添加函数并使用接下来的查询进行测试
sp_configure 'clr enabled', 1
RECONFIGURE WITH OVERRIDE
-- Drop des fonctions pré-existantes
IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.RegExMatches')) DROP FUNCTION dbo.RegExMatches
GO
IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.RegExNbMatches')) DROP FUNCTION dbo.RegExNbMatches
GO
IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.RegExMatchesSplit')) DROP FUNCTION dbo.RegExMatchesSplit
GO
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.objects WHERE object_id = OBJECT_ID(N'dbo.RegExMatch')) DROP FUNCTION dbo.RegExMatch
GO
-- Drop de l'assembly pré-existante puis recréation de celle-ci
IF EXISTS ( SELECT 1 FROM sys.assemblies asms WHERE asms.name = N'RegExFunction' ) DROP ASSEMBLY [RegExFunction]
CREATE ASSEMBLY RegExFunction FROM 'C:\CLR\Regex\RegularExpressionFunctions.dll' WITH PERMISSION_SET = SAFE
GO
-- Création des fonctions
CREATE FUNCTION dbo.RegExMatches(@pattern NVARCHAR(MAX), @sentence NVARCHAR(MAX), @separator NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
AS EXTERNAL NAME RegExFunction.[XXX.DotNet.XXX.RegularExpressionFunctions].RegExMatches
GO
CREATE FUNCTION dbo.RegExNbMatches(@pattern NVARCHAR(MAX), @sentence NVARCHAR(MAX)) RETURNS INT
AS EXTERNAL NAME RegExFunction.[XXX.DotNet.XXX.RegularExpressionFunctions].RegExNbMatches
GO
--CREATE FUNCTION dbo.RegExMatchesSplit(@pattern NVARCHAR(MAX), @sentence NVARCHAR(MAX)) RETURNS TABLE (Sujet NVARCHAR(MAX), Match NVARCHAR(MAX))
CREATE FUNCTION dbo.RegExMatchesSplit(@pattern NVARCHAR(MAX), @sentence NVARCHAR(MAX)) RETURNS TABLE (Match NVARCHAR(MAX))
AS EXTERNAL NAME RegExFunction.[XXX.DotNet.XXX.RegularExpressionFunctions].RegExMatchesSplit
GO
CREATE FUNCTION dbo.RegExIsMatch(@pattern NVARCHAR(MAX), @sentence NVARCHAR(MAX)) RETURNS BIT
AS EXTERNAL NAME RegExFunction.[XXX.DotNet.XXX.RegularExpressionFunctions].RegExIsMatch
GO
CREATE FUNCTION dbo.RegExMatch(@pattern NVARCHAR(MAX), @sentence NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
AS EXTERNAL NAME RegExFunction.[XXX.DotNet.XXX.RegularExpressionFunctions].RegExMatch
GO
使用以下查询来测试您的功能
DECLARE @sentence NVARCHAR(MAX)
DECLARE @regex NVARCHAR(MAX)
DECLARE @regex2 NVARCHAR(MAX)
DECLARE @separator NVARCHAR(MAX)
SET @sentence = 'ABABCCADSQDJIOAZF JAIPZDJKL MNJKCXNjnaze iodjazpdjadpazdoa zdjio'
SET @regex = '[A-z]{6}\ '
SET @regex2 = '^[^a-z]*ABC[^a-z]*$'
SET @separator = ';'
SELECT @regex as 'Regex', @sentence as 'Sentence', dbo.RegExMatch(@regex2, match) FROM dbo.RegExMatchesSplit(@regex, @sentence);
SELECT @regex as 'Regex', @sentence as 'Sentence', dbo.RegExMatches(@regex2, dbo.RegExMatches(@regex, @sentence, @separator), @separator)
SELECT @regex as 'Regex', @sentence as 'Sentence', dbo.RegExNbMatches(@regex,@sentence)
SELECT @regex as 'Regex', @sentence as 'Sentence', dbo.RegExIsMatch(@regex,@sentence)
SELECT @regex as 'Regex', @sentence as 'Sentence', dbo.RegExMatch(@regex2, dbo.RegExMatch(@regex,@sentence))
GO