使用正则表达式匹配 SQL 查询

Posted

技术标签:

【中文标题】使用正则表达式匹配 SQL 查询【英文标题】:Match SQL queries using Regular Expressions 【发布时间】:2017-06-18 21:26:56 【问题描述】:

我想匹配可能具有不同参数的相同类型的 SQL 查询。例如

SELECT Name 
FROM Production.Product 
WHERE Name = 'Bearing Ball' and ProductNumber = 'BA-8327'

SELECT Name 
FROM Production.Product 
WHERE Name = 'Cycle' and ProductNumber = 'CY-1234'

是相同类型的查询,但参数不同。基本上任何东西都可以代替第一个示例中的“轴承球”和“BA-8327”。参数可以是带或不带空格的字符串、数字或日期。我尝试了以下表达式:

var result = new Regex("SELECT Name FROM Production.Product WHERE Name = '*' and ProductNumber = '*'").IsMatch(query)

它没有按预期工作。请给我一个解决方案。

【问题讨论】:

“未按预期工作”信息不足。请提供您expect 发生的事情以及happened 发生的事情。 【参考方案1】:

* 不是通配符。我将其替换为('([^']|'')*'|\d+),它匹配包含' 或连续''(转义单引号)0 次或多次以外的字符的单引号字符串。或者,它匹配 1 个或多个连续数字。

之前有一篇文章(已删除)提到转义 . 通配符。这是一个很好的建议,我也更新了我的答案以反映这一点。

var result = new Regex(@"SELECT Name FROM Production\.Product WHERE Name = ('([^']|'')*'|\d+) and ProductNumber = ('([^']|'')*'|\d+)").IsMatch(query);

【讨论】:

您的答案适用于没有数字的查询,例如此查询中的“SELECT Name FROM Production.Product WHERE Name = 'Bearing Ball' and ProductNumber = 1” 我有一个整数where 子句,所以它不起作用。如何修改 '([^']|'')+' 以在单引号内查找字符串以及不带引号的整数。 @Deepan - 根据您的说明,我已更新我的正则表达式以捕获除字符串之外的整数。请查看我的更新答案。【参考方案2】:

这是一个在正则表达式解析后将所有重要数据转换为动态实体的系统。这样您就可以确定操作是否相同。否则,您可以查看模式并向您的模式添加内容以正确读取数据,例如使用 \x27([^\x27]+)\x27 匹配符合您模式需求的 'Bearing Ball'


string pattern = @"
^                     # Start of the line
select\s              # Anything not in brackets do not capture.
(?<What>[^\s]+)       # Capture a name most likely
\sfrom\s
(?<Table>[^\s]+)      # Capture Table name
\swhere\s
\1                    # Name(?) the what, must be used again
\s*=\s*
\x27                  # \x27 is a single quote '
(?<Name>[^\x27]+)     # Read up to the next quote for the what.
\x27
\s+and\s+ProductNumber\s*=\s*
\x27
(?<ProdNumber>[^\x27]+)  # Read up to the next quote for the product number.
";

string data = @"
SELECT Name FROM Production.Product WHERE Name = 'Bearing Ball' and ProductNumber = 'BA-8327'
SELECT Name FROM Production.Product WHERE Name = 'Cycle' and ProductNumber = 'CY-1234'
";

// IgnorePatternWhitespace lets us space out and comment the pattern code only. Does not affect regex processing.
Regex.Matches(data, pattern, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline)
     .OfType<Match>()
     .Select(mat => new
     
        Table = mat.Groups["Table"].Value,
        What = mat.Groups["What"].Value,
        Name  = mat.Groups["Name"].Value,
        ProductNumber = mat.Groups["ProdNumber"].Value
     );

2 个动态实体的结果

【讨论】:

【参考方案3】:

查看 Arvind Shyamsundar 在 MSDN 上的博客文章,这正是您正在寻找的内容,并且可以进行更多调整。它使用 ScriptDom 类、Microsoft 自己的 T-SQL 解析器和生成器代码,这似乎比尝试自己解析 T-SQL 之类的复杂语言要好得多。 Normalizing T-SQL text using the transactsql scriptdom classes

请注意,一组名为 ScriptDom 的类存在于 2 个不同的命名空间中。自 SQL Server 2012 起,您应该使用的那个随 SQL Server 一起提供,并且具有 Microsoft.SqlServer.TransactSql.ScriptDom 的名称空间。具有名称空间 Microsoft.Data.Schema.ScriptDom 的版本是一个旧的、不太有效的版本,曾经随 Visual Studio 一起提供。您不应再在任何新项目中使用后者。

【讨论】:

以上是关于使用正则表达式匹配 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

oracle10g中,如何查询正则表达式匹配指定字符串的匹配个数?

数据库笔记-SQL过滤(LIKE&正则表达式)

SQL中常用模糊查询的四种匹配模式&&正则表达式

如何用正则表达式匹配指定字符开始和指定字符结束?

oracle10g中,如何查询正则表达式匹配指定字符串的匹配个数?

如何在 Pl/SQL 中编写正则表达式匹配模式?