2012-12-20 22 views
3

我需要为C#构建一个正则表达式,以捕获select子句中的'from'关键字之后的所有表名。例如如何在C#中使用正则表达式获取所有表名?

. 
. 
. 
SELECT field1, field2 
FROM table1 
WHERE condition1 
. 
. 
. 
SELECT field3, field4 
FROM table2 
WHERE condition2 
. 
. 
. 

里有文件的多个选择条款,我尝试阅读,并且可以有选择之间的任何字符(包括新行,“:”,“_”和其他任何字符) 。 我应该如何构建我的正则表达式以获取所有表名称?

感谢

编辑: 我已经找到一个办法让所有的表名。

\s*SELECT[^;]*FROM\s*(?<key>[^\n]*) 

这可能会在某天帮助某人。 感谢

+0

当我尝试'SELECT [\ D | \ d] * FROM(? [^ \ n] *)'时,它发现一个匹配以第一个选择开始并一直延伸到最后一个。我反而希望它匹配所有选择并返回其所有表名。 – Alpay

+0

给这个网站一试,总是帮我找出RegExes http://regexpal.com/ – Charleh

+0

@Charleh是为JavaScript正则表达式。对于.NET,你应该使用[RegexHero](http://regexhero.net) –

回答

3

除非所有查询都只有一张桌子,没有有趣的业务,评论,使用正则表达式,这是一个亏本生意。相反:

SET SHOWPLAN_ALL ON; 

--All your queries here 

请参阅set showplan_all文档编号:

当我说正则表达式会变得复杂时,这就是我的意思。这些只是的考虑的一些

  • 你必须检测被引用字符串的开始:"',并[而忽略所有字符内,直到正常终止。如果结束字符加倍,则不要终止(即,'this is ''fun'', he said'不会在is后停止)。

  • 您必须排除不在引号内的单行注释--,并在下一个CRLF处终止它们。引用标记内的注释不会像往常一样启动字符串。

  • 你必须排除多行注释(从/*)不在引号内或单行注释的内部,然后跳过一切,除了终止,*/。在你的正则表达式中,请务必使用反斜杠\来跳过*字符。

  • 你必须然后找到有效FROM条款与适当的单词边界(列名SelfRomAfroMonkey没有错误匹配,例如)。

  • 为正确端接FROM子句中,你有当你看到包括任何关键字停止捕获WHEREGROUP BYHAVINGORDER BYWITH;既然有分号终止; SQL查询不需要那么你也将不得不终止在SELECTDBCCSETCREATEALTERDROP等等等等。

  • 但即使前面两点是不够真正的自己,因为如果您的查询是什么样子的:

    SELECT * 
    FROM 
        MyTable T 
        INNER JOIN (
         SELECT * FROM YourTable Y WHERE Active = 1 
        ) X ON T.ID = Y.ID 
        INNER JOIN AnotherTable A 
         ON X.AID = A.AID 
    

    现在你必须分析的括号内不停止捕获FROM子句,当你看到任何这些关键字。而且你必须跟踪你深处的括号,并保持忽略,直到你有那么多。最后,你如何处理这些问题,因为派生表就像一个表 - 你想要派生表的全​​文还是仅仅是内部的表?

要做到这一切,你不能刚开始在文本的第一个有效FROM匹配,因为这可能是行情或意见的内部。您必须从头开始匹配所有文本,因为这是正则表达式确保您找不到匹配的唯一方法。

这是我想出的,只是试图处理评论。甚至没有引号。它只能从条款中找到,而不是其中的内容。另外,我们必须防止括号被捕获,因此在检查我们的捕获组以查找实际的FROM子句时,我们没有太大的混乱。

(?:(?:-(?!-)|/(?!\*)|f(?!rom)|[^-f/])|--[^\n]*\n|/\*(?:\*/)*\*/)*from() 

而且它可能有错误的盛行,我不得不重新考虑整个事情一旦我用它玩了一下,所有的一切,这将是一次一个巨大的浪费。

我认为你低估了这样的事情会很难完成。但是有一个非常可靠的解决方案!我上面给出的一个:让SQL Server为你解析所有的东西。您可以轻松解析返回的计划,因为它的结构方式使其变得简单。

1

首先我想说看看这个教程:http://www.codeproject.com/Articles/9099/The-30-Minute-Regex-Tutorial

退房这样的正则表达式:((?<=FROM)[^\s]+)

此正则表达式将开始"FROM "(包括空格)后,直接读取并停止在读第一空白(^\s)

,如果你尝试这样

foreach (Match m in Regex.Matches(input, @"((?<=FROM)[^\s]+)") 
{ 
    string output = m.Value; 
} 

编辑:

我不是100%确定这个正则表达式。如果你的名字末尾有一个换行符,这个woudl可能会更好地完成这项工作:@"((?<=FROM)[^\n]+))但是你应该修剪输出,因为输出字符串的开始处可能有一个空格。

+0

FORM!==从我亲爱的chap – ErikE

+0

@ErikE对不起,误读了..变了! – 2pietjuh2

0
var input = "select name from Table1 where id =2"; 
var pattern = @"from\s*(.*?)\s*where"; // where car= is the first delimiter and ; is the second one 
var result = Regex.Match(input, pattern).Groups[1].Value; 
MessageBox.Show(result); 
+0

那么说“来自”的评论呢?灾害。 – ErikE

+0

多个查询一起将不会被正确处理 - 结果将跨越所有这些查询。 – ErikE

相关问题