正则表达式解析有限的SQL Where子句
本文关键字:SQL Where 子句 正则表达式 | 更新日期: 2023-09-27 18:15:39
如何使用正则表达式解析有限的SQL where子句?
where-子句的格式受到限制。它不包含子查询。它仅限于"AND"、"OR"answers"()"。
如果给我一个where子句,我想从中提取部分
where-clause的三个例子:
- ProjectNumber = ?
- ProjectNumber = ?AND严重性= 5
- (ProjectNumber = ?AND severity=5) OR DueDate <(DATETIME('现在'))
例如1,我想要"ProjectNumber=?"
例如2,我想要"ProjectNumber =?", "severity = 5"
例如3,我想要"ProjectNumber=?","severity=5","DueDate <"(DATETIME('现在'))"
"?"表示该值是参数化的。
我明白正则表达式不够强大,无法解析完整的SQL where子句。
我发现这种"(& lt; = ^ | ' |和|或 ))(?:[^']|'(?:[^']|'{ 2 })+')*?(?=( 美元和|或)| | ' Z)",但它不工作3 .
编程语言为c#,数据库为SQLite。
注。我对正则表达式有非常基本的经验。
谢谢。
注。下面是我当前的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
您将注意到没有任何东西处理布尔运算符,例如AND或 or 。这是不必要的,因为这些布尔运算符不是正则表达式匹配的模式的一部分。(还记得上面对模式的崇高描述吗?)
如何在c#中使用这样的正则表达式来从WHERE谓词中提取所需的部分?
首先,请注意我将继续在正则表达式中使用空格以提高可读性。这需要使用RegexOptions进行RegEx初始化。IgnorePatternWhitespace或"(?x)"内联选项。在下面的代码中,我使用前者。
要从WHERE谓词中提取所有部分,RegEx。方法,它返回一个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测试器的帮助下在线试验正则表达式和不同的输入字符串。