如何使用.NET正则表达式删除SQL字符串的多个(可选)部分?

时间:2010-04-22 01:14:23

标签: .net sql regex

我已经在这个工作了几个小时了,但却找不到任何帮助。基本上,我正在尝试将SQL字符串分成不同的部分(字段,from,where,having,groupBy,orderBy)。我拒绝相信我是第一个尝试这样做的人,所以我想请求StackOverflow社区提供一些建议。 :)

要了解我的需要,请假设以下SQL字符串:

select * from table1 inner join table2 on table1.id = table2.id 
where field1 = 'sam' having table1.field3 > 0 
group by table1.field4 order by table1.field5 

我创建了一个正则表达式来相应地对部分进行分组:

select\s+(?<fields>.+)\s+from\s+(?<from>.+)\s+where\s+(?<where>.+)\s+having\s+(?<having>.+)\s+group\sby\s+(?<groupby>.+)\s+order\sby\s+(?<orderby>.+)

这给了我以下结果:

fields => *
from => table1 inner join table2 on table1.id = table2.id
where => field1 = 'sam'
having => table1.field3 > 0
groupby => table1.field4
orderby => table1.field5 

我遇到的问题是,如果在'from'子句后缺少任何部分SQL字符串,则正则表达式不匹配。

为了解决这个问题,我尝试将每个可选部分放在它自己的(...)?组中,但这不起作用。它只是将所有可选部分(where,having,groupBy和orderBy)放入'from'组。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

使用.Net正则表达式无法完美地完成此操作;你需要一个基于堆栈的解析器。

如果您不明白为什么,请考虑以下两个有效查询:

SELECT 'I\'m from Kansas', 'where the grass is greener'     
FROM Minnesota 
WHERE Grass = 'Blue'

SELECT 
    ID,
    Name IN (SELECT Name From Employees WHERE Rank > 4),
    Grade
FROM Employees
WHERE Rank < 4

修改

回答这个问题:

new Regex(@"

    ^
    select\s+(?<fields>.+?)
        \s+ from       \s+ (?<from>    .+?)
    (?: \s+ where      \s+ (?<where>   .+?))?
    (?: \s+ having     \s+ (?<having>  .+?))?
    (?: \s+ group\s+by \s+ (?<groupby> .+?))?
    (?: \s+ order\s+by \s+ (?<orderby> .+ ))?
    $", 

        RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

(再测试)
这不会处理嵌套查询或字符串文字