gpt4 book ai didi

c# - 正则表达式解析有限的 SQL Where 子句

转载 作者:行者123 更新时间:2023-11-30 19:59:06 25 4
gpt4 key购买 nike

如何使用正则表达式解析有限的 SQL where 子句?

where 子句的格式受到限制。它不会包含子查询。它仅限于“AND”、“OR”和“()”。

因此,如果给我一个 where 子句,我想从中提取部分。

where子句的3个例子:

  • 项目编号=?
  • 项目编号 =? AND 严重性 = 5
  • (ProjectNumber=? AND severity=5) OR DueDate < (DATETIME('NOW'))

  • 例如 1,我想要“ProjectNumber=?”

    例如2,我想要“ProjectNumber =?”,“severity = 5”

    例如 3,我想要“ProjectNumber=?”、“severity=5”、“DueDate < (DATETIME('NOW'))”

    这 ”?”表示该值是参数化的。

    我知道正则表达式不足以解析完整的 SQL where 子句。

    我找到了这个 "(?<=^|\A|(AND|OR))(?:[^']|'(?:[^']|'{2})+')*?(?= (AND|OR)|$|\Z)"但它不适用于 3。

    编程语言是 C#,数据库是 SQLite。

    p.s.我对正则表达式有非常基本的经验。

    谢谢。

    p.s.以下是我当前的 C# 代码:
    string query = @"(ProjectNumber=? AND severity=5) OR DueDate < (DATETIME('NOW'))";
    string pattern = @"(?<=^|\A|(AND|OR))(?:[^']|'(?:[^']|'{2})+')*?(?=(AND|OR)|$|\Z)";
    MatchCollection matches = Regex.Matches(query, pattern);
    foreach (Match match in matches)
    Console.WriteLine(match.ToString());
    // currently Console.WriteLine() gives the following:
    // (ProjectNumber=?
    // severity=5)
    // DueDate < (DATETIME('NOW'))

    最佳答案

    使用您对 SQL WHERE 谓词施加的限制,可以创建一个正则表达式来提取比较表达式,同时考虑 (DATETIME('NOW')) 等结构。

    我将展示和解释的正则表达式要求 WHERE 谓词在语法上是正确的。如果 WHERE 谓词有语法错误,则正则表达式可能不匹配或产生垃圾结果。

    完整的正则表达式(添加空格以增强可读性!):

    \w[\w\d]* \s*[<>=]{1,2}\s* ( \?|\w[\w\d]*|(\w[\w\d]*)*((?<PR>\()|(?<-PR>\))|[^()])+ )

    虽然它肯定不是一个很长的正则表达式,但它仍然很难阅读和理解。因此,让我们解构这个正则表达式并解释它的几个部分。为此,我们将首先看看我们真正想要从 WHERE 谓词中提取的内容。

    我们想从 WHERE 谓词中提取的每个表达式都遵循相同的基本模式:
    SomeIdentifierWithoutParantheses =|<=|>=|<> SomeOtherThingWithOrWithoutParentheses

    这种(a 的高级描述)模式足以理解正则表达式需要匹配的内容以从 WHERE 谓词中提取所需部分。

    我们正则表达式中的第一部分 \w[\w\d]* 匹配 SomeIdentifierWithoutParantheses。这可以是任何以字母数字字符开头,后跟其他字母数字字符和/或数字的标识符。此类标识符的示例是 ProjectNumber 和 My1Ident23。

    正则表达式的第二部分 \s*[<>=]{1,2}\s* 匹配比较操作数 =<=>=<> ,包括比较运算符前后的任何空格。 (好吧,它也会匹配像 =< 这样的废话,但是 - 正如一开始所说 - 我们假设语法正确的 SQL。)

    正则表达式的第三部分匹配比较运算符之后的第二个操作数,这看起来确实有点笨拙: ( \?|\w[\w\d]*|(\w[\w\d]*)*((?<PR>\()|(?<-PR>\))|[^()])+ ) 。让我们进一步解构正则表达式的这一部分。正如您可能已经注意到的那样,整个事情是三个替代选项的交替,这将在下面进行解释。
    \? 显然匹配一个问号(如“ProjectNumber=?”)。 \w[\w\d]* 匹配标识符的方式与匹配第一个操作数的方式相同。
    (\w[\w\d]*)*((?<PR>\()|(?<-PR>\))|[^()])+ 包含 .NET 中 RegEx 引擎的一个特性:平衡组。使用具有平衡组的这种构造允许正则表达式匹配包含(嵌套)括号组 ( - ) 的操作数,例如 DATETIME('NOW') 或 (DATETIME('NOW'))。

    对于 StackOverflow 上的另一个问题,Martin Büttner 对平衡组给出了很好的解释(问题的主题是“ What are regular expression Balancing Groups?”),我想向任何不了解平衡组的人指出他的答案( click here to navigate to Martin's answer)。另一个很好的解释可以在 CodeProject 上找到。

    您会注意到没有任何东西可以处理诸如 AND 或 OR 之类的 bool 运算符。这不是必需的,因为这些 bool 运算符不是正则表达式匹配的模式的一部分。 (还记得上面对模式的崇高描述吗?)

    在 C# 中如何使用这样的正则表达式从 WHERE 谓词中提取所需的部分?

    首先,请注意我将继续在正则表达式中使用空格以提高可读性。这需要使用 RegexOptions.IgnorePatternWhitespace 或“(?x)”内联选项进行 RegEx 初始化。在下面的代码中,我使用前者。

    要从 WHERE 谓词中提取所有部分,将使用 RegEx.Matches 方法,该方法返回 Match 对象的集合。每个 Match 对象代表一个提取的部分。
    Regex re = new Regex(
    @"\w[\w\d]* \s*[<>=]{1,2}\s* ( \?|\w[\w\d]*|(\w[\w\d]*)*((?<PR>\()|(?<-PR>\))|[^()])+ )",
    RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled
    );


    string wherePredicate =
    "(ProjectNumber=? AND severity=5) OR DueDate < (DATETIME('NOW'))";
    // or use any other WHERE predicate string here...

    MatchCollection mc = re.Matches(wherePredicate);

    if (mc.Count == 0)
    Console.WriteLine("No matches found.");
    else
    foreach (Match m in mc)
    Console.WriteLine("\"{0}\"", m.Value);

    您可以借助 Regex Storm .NET Regex tester 在线试验正则表达式和不同的输入字符串。

    关于c# - 正则表达式解析有限的 SQL Where 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25049855/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com