我上周正在为一段生成一些SQL语句的代码编写一些单元测试。
我试图找出一个匹配SELECT,INSERT和UPDATE语法的正则表达式,这样我就可以验证我的方法是否生成了有效的SQL,经过3-4个小时的搜索和乱搞各种正则表达式编辑后,我放弃了。
我设法获得了部分匹配,但因为引号中的部分可以包含任何字符,所以它会快速扩展以匹配整个声明。
任何帮助都会受到赞赏,我对正则表达式不是很了解,但我想了解更多关于它们的信息。
顺便说一下,我是C#正则表达式。
澄清
我不想要访问数据库,因为这是单元测试的一部分,我不需要维护数据库来测试我的代码。这可能比项目更长寿。
答案 0 :(得分:37)
正则表达式只能匹配有限状态自动机可以解析的语言,这是非常有限的,而SQL是一种语法。 可以证明您无法使用正则表达式验证SQL。因此,您可以停止尝试。
答案 1 :(得分:14)
SQL是type-2 grammar,它太强大了,不能用正则表达式来描述。它就像你决定生成C#代码然后在不调用编译器的情况下验证它一样。数据库引擎通常太复杂而不容易存根。
也就是说,您可以尝试ANTLR's SQL grammars。
答案 2 :(得分:2)
据我所知,这超出了正则表达式,你接近BnF和编译器的黑暗艺术。
想要进行正确语法突出显示的人也会遇到同样的事情。你开始把事情塞进正则表达式,然后你最终编写了一个编译器......
答案 3 :(得分:1)
我的头脑:你不能将生成的SQL传递给数据库并对它们使用EXPLAIN并捕获任何表明SQL格式不正确的异常吗?
答案 4 :(得分:1)
我有同样的问题 - 一种适用于所有更标准的sql语句的方法是启动内存中的Sqlite数据库并针对它发出查询,如果你找回“表不存在”错误,然后您的查询正确解析。
答案 5 :(得分:0)
你有没有尝试过懒惰的选择器。它们尽可能地匹配,而不是尽可能匹配,这可能是你需要的引号。
答案 6 :(得分:0)
要验证查询,只需使用SET NOEXEC ON运行它们,这就是Entreprise Manager在解析查询时不执行它的方式。
此外,如果您使用正则表达式验证SQL查询,您几乎可以肯定您会错过某些极端情况,或者由于其他原因查询无效,即使它在语法上是正确的。
答案 7 :(得分:0)
我建议使用相同的模式创建一个数据库,可能使用嵌入式sql引擎,并将sql传递给它。
答案 8 :(得分:0)
我认为你甚至不需要创建模式来验证语句,因为系统在成功解析语句之前不会尝试解析object_name等。
以Oracle为例,如果您这样做,肯定会出错:
select * from non_existant_table;
在这种情况下,“ORA-00942:表或视图不存在”。
但是如果执行:
select * frm non_existant_table;
然后你会得到一个语法错误,“ORA-00923:在预期的地方找不到FROM关键字”。
应该可以将错误分类为语法分析错误,指出与表名和权限等相关的错误语法和错误。
除此之外,还有不同RDBMS的问题,甚至不同的版本允许使用不同的语法,我认为你真的必须转到db引擎来完成这项任务。
答案 9 :(得分:0)
有ANTLR grammars来解析SQL。使用in memory database或非常轻量级的数据库(例如sqlite)确实更好。从解析的角度来测试SQL是否有效对我来说似乎很浪费,而且检查表和列名以及查询的细节会更有用。
答案 10 :(得分:0)
最好的方法是验证用于创建查询的参数,而不是查询本身。接收变量的函数可以检查字符串的长度,有效数字,有效电子邮件或其他内容。您可以使用正则表达式来执行此验证。
答案 11 :(得分:-1)
我假设你做了类似“。*”之类的尝试而不是“[^”] *“这会让你不吃整条线。它仍然会对你在你的字符串里面的情况给出误报。
答案 12 :(得分:-1)
public bool IsValid(string sql)
{
string pattern = @"SELECT\s.*FROM\s.*WHERE\s.*";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
return rgx.IsMatch(sql);
}