【问题标题】:Using regular expressions to scan T-SQL for object dependencies使用正则表达式扫描 T-SQL 的对象依赖关系
【发布时间】:2012-01-12 14:56:42
【问题描述】:

我正在编写一个 c# 类库,它允许我扫描 SQL 服务器查询并将查询中的对象提取到正确的分组中,例如:

SELECT * FROM "My Server"."Northwind"."dbo"."Product Sales for 1997" Group By CategoryID

这个正则表达式将匹配上面的字符串并将“My Server”、“Northwind”、“dbo”和“Product Sales for 1997”分成四组,这就是我想要的。

(?i)\bFROM\b\s+[\["]([^\]"]*)[\]"].{1}[\["]([^\]"]*)[\]"].{1}[\["]([^\]"]*)[\]"].{1}[\["]([^\]"]*)[\]"].{1}

我正在寻找的是一个单一的正则表达式,它可以为以下任何组合捕获服务器名称、数据库名称、模式名称和对象名称(无论如何这不是一个详尽的列表):

SELECT * FROM dbo."Product Sales for 1997" // should return groups 2 & 3
SELECT * FROM Northwind."My Schema"."My view or table function" // should return  groups 1, 2 & 3
SELECT * FROM "My view or table function" // should return group 3
SELECT * FROM dbo."My View 1" AS V1 JOIN "My View 1" AS V2 ON V1.ID = V2 // should return groups 2 & 3

换句话说,我想将各种组件分为以下几组:

组 0 --> 服务器名称
第 1 组 --> 数据库名称
第 2 组 --> 架构
第 3 组 --> 对象名称

我试图避免创建多个正则表达式来处理每个可能的组合,以避免我的类库变得太大和复杂,但作为一个正则表达式 n00b,它被证明有点困难。

【问题讨论】:

  • 正则表达式不适合这个。你需要一个解析器。例如Microsoft.Data.Schema.ScriptDom
  • 感谢您的快速响应,但是由于时间限制和编写解析器的复杂性,编写解析器是不可能的。我可以使用任何预先存在的 T-SQL 解析器吗?我确实设法编写了正则表达式来从 EXEC 语句中提取组件,但只有在对象名称中没有空格时才有效。我很快意识到,要涵盖所有组合,我最终会得到太多我真正想要的正则表达式。
  • Microsoft.Data.Schema.ScriptDom 同上。如果这对您不可用,请参阅 OP in this question 的 cmets 以获得另一种选择。
  • 我会看看那些。非常感谢!
  • 解析器是个好主意,但是如果你需要一个快速的正则表达式修复,从示例中看起来像当你有 xxx.xxx.xxx.xxx 它是组 0,1,2,3 ; xxx.xxx.xxx 是 1,2,3; xxx.xx 是 2,3; xxx 是 3。然后你可以将 \bFROM\b\s+(?:(?:(?:xx)?xx)?xx)?xx 作为你的正则表达式,xx 是你上面的正则表达式,[\["]([^\]"]*)[\]"].{1}。 (还要注意.{1} 是多余的;. 可以)。

标签: c# sql regex


【解决方案1】:

使用正则表达式的最佳方法是将其解析为标记,然后必须确定组的实际值(服务器数据库等)是什么。这是一个正则表达式,用于将您的数据示例转换为此类令牌。注意我不知道 sql server 有引号,但是您的示例要求使用引号,因此我使用 If 条件分别查找转义为 \x22 和 \x27 的单引号和双引号(请参阅我的博客文章 Regular Expressions and the If Conditional)。令牌被放置在提取它们的匹配捕获中。

string data =
@"SELECT * FROM dbo.""Product Sales for 1997"" // should return groups 2 & 3 
SELECT * FROM Northwind.""My Schema"".""My view or table function"" // should return  groups 1, 2 & 3 
SELECT * FROM ""My view or table function"" // should return group 3 
SELECT * FROM dbo.""My View 1"" AS V1 JOIN ""My View 1"" AS V2 ON V1.ID = V2 // should return groups 2 & 3 ";

string pattern = 
@"
(?:FROM\s+)                 # Work from a from only
(
  (?([\x27\x22])            # If a single or double quote is found      
     (?:[\x27\x22])
       (?<Tokens>[\w\s]+)   # process quoted text
     (?:[\x27\x22]\.?)
   |                        # else
     (?!\s+AS|\s+WHERE)     # if AS or Where is found stop the match we are done
     (?:\.?)
     (?<Tokens>\w+)         # Process non quoted token.
     (?:\.?)
   )
   (?![\n\r/])              # Stop on CR/LF or a comment. 
){0,4}                      # Only do this 1 to 4 times, for it can't be more (parser hint to stop)
";

Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace) // Ignore is to allow commenting of the pattern only (not data processing)
    .OfType<Match>()
    .Select(mt => mt.Groups["Tokens"]
                    .Captures.OfType<Capture>()
                    .Select(cp => cp.Value))
    .ToList() // To do the foreach below
    .ForEach(tokens => Console.WriteLine(string.Join(" | ", tokens)));

/* Output
dbo | Product Sales for 1997
Northwind | My Schema | My view or table function
My view or table function
dbo | My View 1
*/

【讨论】:

    【解决方案2】:

    要解析任意 SQL 查询,最好使用SQL parser。尝试使用正则表达式解析任意 SQL 相当于编写自己的解析器。

    在完整的 SQL 解析器的帮助下,很容易实现您所需要的:

    SELECT * FROM Northwind."My Schema"."My view or table function";
    

    输出将是这样的:

    select clause:
    Columns
    Fullname:*
    Prefix: Column:*    alias:
    
    from clause:
       Northwind."My Schema"."My view or table function"
    
    database: Northwind
    schema:   "My Schema"
    object:   "My view or table function"
    object alias:
    

    您可以自己尝试this demo 来测试更复杂的 SQL 查询。

    【讨论】:

      猜你喜欢
      • 2017-06-18
      • 2016-01-23
      • 2013-04-10
      • 1970-01-01
      • 2011-03-16
      • 2011-12-07
      • 1970-01-01
      • 2016-09-28
      • 2010-09-16
      相关资源
      最近更新 更多