Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用正则表达式扫描T-SQL中的对象依赖项_C#_Sql_Regex - Fatal编程技术网

C# 使用正则表达式扫描T-SQL中的对象依赖项

C# 使用正则表达式扫描T-SQL中的对象依赖项,c#,sql,regex,C#,Sql,Regex,我正在编写一个c类库,它允许我扫描SQL server查询并将查询中的对象提取到正确的分组中,例如: SELECT * FROM "My Server"."Northwind"."dbo"."Product Sales for 1997" Group By CategoryID 这个正则表达式将匹配上面的字符串,并将我的服务器、Northwind、dbo和1997年的产品销售分为四个组,这就是我想要的 (?i)\bFROM\b\s+[\["]([^\]"]*)[\]"].{1}[\["]([^

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

SELECT * FROM "My Server"."Northwind"."dbo"."Product Sales for 1997" Group By CategoryID
这个正则表达式将匹配上面的字符串,并将我的服务器、Northwind、dbo和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组->对象名称


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

使用regex可以做的最好的事情是将它解析为令牌,然后必须确定组的实际服务器数据库等是什么。下面是一个正则表达式,用于将数据示例转换为此类令牌。注意,我不知道sql server有引号,但您的示例要求使用引号,因此我使用If条件see my blog文章查找分别转义为\x22和\x27的单引号和双引号。标记被放入匹配捕获中,并在其中提取

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
*/

使用regex最好的方法是将其解析为令牌,然后必须确定组的实际服务器数据库等。下面是一个正则表达式,用于将数据示例转换为此类令牌。注意,我不知道sql server有引号,但您的示例要求使用引号,因此我使用If条件see my blog文章查找分别转义为\x22和\x27的单引号和双引号。标记被放入匹配捕获中,并在其中提取

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
*/

要解析任意SQL查询,最好使用一个。尝试用正则表达式解析任意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:

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

要解析任意SQL查询,最好使用一个。尝试用正则表达式解析任意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:

您可以自己测试更复杂的SQL查询。

正则表达式不适合这种情况。你需要一个解析器。e、 感谢您的快速响应,但是由于时间限制和编写解析器的复杂性,编写解析器是不可能的。我可以使用任何预先存在的T-SQL解析器吗?我确实成功地编写了正则表达式来从EXEC语句中提取组件,但只有在对象名称中没有空格时才有效。我很快意识到,要覆盖所有的组合,我最终会得到太多我真正想要的正则表达式。如果你不知道,请看OP的评论,我会看一看。非常感谢!解析器是一个好主意,但是如果您需要快速的正则表达式修复,从示例来看,当您有xxx.xxx.xxx.xxx时,它是0,1,2,3组;对于xxx.xxx.xxx,它是1,2,3;对于xxx.xx,它是2,3;xxx是3。然后您可以从\b\s+?:?:xx?xx?xx?xx?xx作为您的正则表达式,其中xx是您上面的正则表达式,[\[[^\]*[\].{1}。请注意,{1}是多余的。可以。正则表达式不适合这种情况。你需要一个解析器。e、 感谢您的快速响应,但是由于时间限制和编写解析器的复杂性,编写解析器是不可能的。我可以使用任何预先存在的T-SQL解析器吗?我确实成功地编写了正则表达式来从EXEC语句中提取组件,但只有在对象名称中没有空格时才有效。我很快意识到,要覆盖所有的组合,我最终会得到太多我真正想要的正则表达式。如果你不知道,请看OP的评论,我会看一看。非常感谢!解析器是一个好主意,但是如果您需要快速的正则表达式修复,从示例来看,当您有xxx.xxx.xxx.xxx时,它是0,1,2,3组;对于xxx.xxx.xxx,它是1,2,3;对于xxx.xx,它是2,3;xxx是3。然后您可以从\b\s+?:?:xx?xx?xx?xx?xx作为您的正则表达式,其中xx是您上面的正则表达式,[\[[^\]*[\].{1}。请注意,{1}是多余的。可以。