【问题标题】:Regex in SQL Server, match anything except a letterSQL Server 中的正则表达式,匹配除字母以外的任何内容
【发布时间】:2017-06-23 12:24:18
【问题描述】:

我正在尝试在 SQL Server 中编写一些正则表达式来匹配除字母之外的字符串之前或之后的任何内容。

'%ABC%' 不起作用,因为它包含字母。

'%[^a-z]ABC[^a-z]%' 不起作用,因为它不会与结果以ABC 开头或结尾的任何查询匹配。因为[^a-z] 表示任何不是字母字符但仍然是字符的字符。

解决这个问题的正则表达式是:

[^a-z]ABC[^a-z]|ABC[^a-z]|[^a-z]ABC

但你不能在 SQL 中这样写:

'%[^a-z]ABC[^a-z]|ABC[^a-z]|[^a-z]ABC%'

'%[^a-z]ABC[^a-z]%|%ABC[^a-z]%|%[^a-z]ABC%'

我不想在我的 SQL 中使用 OR,因为我有一个存储过程,其中包括:

WHERE var like @var 

我会用类似的东西来执行它

@var = '%[^a-z]APU[^a-z]%'

我宁愿没有多个参数,或者尝试将多个值传递给单个参数。

有没有办法调整'%[^a-z]ABC[^a-z]%' 的正则表达式,使ABC 可以开始或结束字符串?

【问题讨论】:

  • 请提供样本数据和期望的结果。这在 SQL Server 中完全有效:'%[^a-z]APU[^a-z]%'。你的问题没有意义。
  • '%[^a-z]ABC[^a-z]%' 不是 regex,它是通配符模式。
  • @Olivia 在这里检查我想你会解决here
  • 请检查我的答案是否有效。 :)

标签: sql sql-server regex string


【解决方案1】:

你可以这样做:

where ' ' + var + ' ' like '%[^a-z]ABC[^a-z]%'

这也将匹配字符串开头和结尾的模式。

不过,我不确定这是否真的满足您的要求。

【讨论】:

    【解决方案2】:

    您还可以使用此 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
    

    【讨论】:

      猜你喜欢
      • 2013-02-27
      • 1970-01-01
      • 2022-12-09
      • 2016-01-16
      • 2016-01-16
      • 1970-01-01
      • 2019-02-15
      • 1970-01-01
      • 2011-10-06
      相关资源
      最近更新 更多