正则表达式:SQL语句是否包含WHERE子句?

时间:2010-09-15 01:43:26

标签: sql regex where-clause

我需要一个正则表达式来确定给定的SQL语句是否有WHERE子句。我的问题是传递的SQL语句很可能很复杂,所以我不能仅仅依赖于语句中WHERE这个词的存在。

例如,这应匹配

SELECT Contacts.ID
     , CASE WHEN (Contacts.Firstname IS NULL) THEN ''
            ELSE CAST(Contacts.Firstname AS varchar)
       END AS Firstname
     , CASE WHEN (Contacts.Lastname IS NULL) THEN ''
            ELSE CAST(Contacts.Lastname AS varchar)
       END AS Lastname
     , CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
                  tbl_ContactExtras.Prequalified IS NULL) THEN ''
            WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
            WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
            WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
            ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
       END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID
WHERE (Contacts.Firstname LIKE 'Bob%')

这不应该匹配:

SELECT Contacts.ID
     , CASE WHEN (Contacts.Firstname IS NULL) THEN ''
            ELSE CAST(Contacts.Firstname AS varchar)
       END AS Firstname
     , CASE WHEN (Contacts.Lastname IS NULL) THEN ''
            ELSE CAST(Contacts.Lastname AS varchar)
       END AS Lastname
     , CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
                  tbl_ContactExtras.Prequalified IS NULL) THEN ''
            WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
            WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
            WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
            ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
       END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID

这些是一些较简单的陈述的例子:一个陈述中最多可以包含30个CASE语句,或者根本没有。{/ p>

我需要以编程方式添加WHERE个参数,但正确执行此操作需要知道是否已存在WHERE子句。

关于正则表达式的任何想法都适用于此?如果不是,关于如何区分两者的任何其他想法?

谢谢,

5 个答案:

答案 0 :(得分:2)

这是不可能的,因为WHERE子句可以任意嵌套在FROM子句中。

答案 1 :(得分:1)

这可能无法捕获所有个案,但您可能会发现只能通过查找语句中的最后一个from和最后一个where来捕获大部分。

如果where位于from之后,则它具有where子句。如果where位于from之前(或根本没有where),则不存在where子句。

有时候,可以在代码中留下限制或限制,只要它们被正确记录。

例如,我在解析SQL之前就已经处理了一个项目,我们发现它没有处理像between这样的事情:

where recdate between '2010-01-01' and '2010-12-31'

我们只是将其作为限制发布,并告诉每个人他们必须将其更改为:

而不是花费大量资金来解决问题(并且可能会在路上引入错误)。
where recdate >= '2010-01-01'
  and recdate <= '2010-12-31'

问题解决了。虽然保持客户满意是件好事,但您不必满足每个的心血来潮: - )

除此之外,你需要一个SQL解析器,而SQL 不是一种可以解析的漂亮语言,请相信我。

答案 2 :(得分:0)

所有连接都是一样的吗?如果是这样,你可以找到全部或部分FROM语句的索引(可能使用正则表达式来容忍语法和空格中的细微差别),然后在该索引之后查找单词WHERE的出现。

一般来说,最好使用解析器。但如果这只是一次性的事情,并且陈述都非常相似,那么上述方法应该没问题。

答案 3 :(得分:0)

正则表达式不是为此而设计的。正确解析SQL需要匹配平衡括号(以及其他匹配对,例如引号),正则表达式设计用来做(并且纯正的正则表达式甚至没有配备; PCRE可以,但它不漂亮)

相反,只需编写一个基本状态机或其他东西来解析它。

答案 4 :(得分:0)

你想解决的问题是什么?您是否尝试确定向这些现有查询添加约束是否安全?

例如,如果您有此查询

...
where foo = 'bar'

然后你知道添加

是安全的
and bat = 'quux'

但是如果你还没有WHERE子句,那么你必须以

的方式进行
where bat = 'quux'

这是你要解决的问题吗?如果是这样,您是否可以通过向那些没有查询的查询添加“WHERE 0 = 0”来使您正在使用的每个SQL查询都有WHERE子句?然后,您知道在后处理阶段,每个查询都有一个。

当然,这只是猜测。你的问题听起来可能是更大的问题。