如何检查.sql文件中的SQL语法?

34

我怎样检查.sql文件中的SQL语法?


这需要很多澄清才能变得有用(并保持开放)。您是在询问有关视觉检查SQL的提示吗?您是否正在寻找可以帮助您检查语法的脚本?您是否正在运行脚本,需要帮助理解特定错误? - Bill the Lizard
11
我认为他们希望验证该文件是否具有有效的MySQL语法。 - KM.
视觉检查SQL文件或脚本也可以用来检查语法。 - maxjackie
4
@maxjackie说:“检查SQL文件或脚本的视觉外观也可以用来检查语法。”根据我的经验,人类检查语法不是100%准确的,而数据库是可以的! - KM.
1
在接受一组迁移/回滚脚本的自动化中,知道它们至少通过基本语法检查并在检查失败时失败提交是有很多意义的。 - Danny Staple
7个回答

8
在MySQL 8.0中,SELECT STATEMENT_DIGEST_TEXT可以用于MySQL查询语法验证。
8.0.4>SELECT STATEMENT_DIGEST_TEXT('FLUSH TABLES')\G
STATEMENT_DIGEST_TEXT('FLUSH TABLES'): FLUSH TABLES 

8.0.4>SELECT STATEMENT_DIGEST_TEXT("SET GLOBAL second_cache.key_buffer_size=128*1024;")\G
STATEMENT_DIGEST_TEXT("SET GLOBAL second_cache.key_buffer_size=128*1024;"): SET GLOBAL `second_cache` . `key_buffer_size` = ? * ? ;

8.0.4>SELECT STATEMENT_DIGEST_TEXT("create TABLE t1 ( a2 int unsigned not null, b2 int unsigned not null, c2 int unsigned not null, primary key (a2), index b2x (b2), index c2x (c2) ) ENGINE=MEMORY;")\G
STATEMENT_DIGEST_TEXT("create TABLE t1 ( a2 int unsigned not null, b2 int unsigned not null, c2 int unsigned not null, primary key (a2), index b2x (b2), index c2x (c2) ) ENGINE=MEMORY;"): CREATE TABLE `t1` ( `a2` INTEGER UNSIGNED NOT NULL , `b2` INTEGER UNSIGNED NOT NULL , `c2` INTEGER UNSIGNED NOT NULL , PRIMARY KEY ( `a2` ) , INDEX `b2x` ( `b2` ) , INDEX `c2x` ( `c2` ) ) ENGINE = MEMORY ; 

如果SQL不被支持,你会收到一个错误。就像下面这个例子一样,但是这个响应有些特殊;

8.0.4>SELECT STATEMENT_DIGEST_TEXT('HELP SELECT')\G
ERROR 3676 (HY000): Could not parse argument to digest function: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT' at line 1".

你是否注意到了什么特别之处?那就是'HELP'是一个有效的客户端关键字,但不是服务器关键字。无论如何,无效的SQL语句都会产生类似的情况;即错误。

因此,您可以根据ERROR与NO ERROR来检查传递的SQL语法是否有效(排除非常有限的一些仅限于客户端的命令,但这些对大多数人来说并不感兴趣)。

总之,SELECT STATEMENT_DIGEST_TEXT是一个全面的SQL解析器(虽然可能不是它的直接/预期功能),可用于所有情况下快速检查语句的有效性,而无需实际执行它们。这在SQL有效性验证方面是巨大的进步。

请注意,您需要运行一个MySQL服务器才能进行此操作。您可以使用mysql -e客户端传递查询,或使用管道到mysql等。


6

基本词法分析器似乎是在sql/sql_lex.cc中实现的。您可以使用/拯救它来构建自己的测试解析器。但这只会检查语法而不会检查任何运行时错误。

编辑:对于MySQL 8.0+,请参见如何检查.sql文件中的SQL语法?


1
这种编程解决方案非常有用,例如可以验证mysqldump结果至少在语法上是完整的。 - ClearCrescendo
1
是的,但这样做会很复杂。一种更简单的方法(具有相同的结果); https://dev59.com/_HNA5IYBdhLWcg3wcddk#49701921 - Roel Van de Paar

4
TLDR:
>awk '{print "EXPLAIN " $0}' statements.sql | mysql --force -u user -p database | grep "ERROR"

奇怪的是,mysql没有内置的开关可以使用,但是您可以在查询语句前添加EXPLAIN语句来检查语法。

如果您有一个statements.sql文件,其中每个语句都在一行上,请在具有以下所有行的开头添加EXPLAIN

>awk '{print "EXPLAIN " $0}' statements.sql > check.sql

您可以使用 mysql 命令行工具运行语句,并使用 --force 选项在出现错误时继续执行。对于任何语法有误的语句,它都会打印出错误信息。

>mysql --force -u user -p database < check.sql

或者只查看出现错误的行:

>mysql --force -u user -p database < check.sql | grep "ERROR"

您可以在一行命令中完成所有操作,无需创建中间文件:
>awk '{print "EXPLAIN " $0}' statements.sql | mysql --force -u user -p database | grep "ERROR"

我会添加这个来使文件不需要是单行的。awk '{if (sub(/;$/,";\n")) printf "EXPLAIN %s", $0; else print $0}' statements.sql 结合以分号结尾的行。 - Jon49

1

有一些免费/试用软件可以让您连接到MySQL数据库或只需粘贴脚本以进行验证。在这里,Google是您的朋友。 Mimer将检查ANSI标准语法验证,但可能无法处理任何MySQL特定内容。


1
你可以将其粘贴到类似MySQL查询浏览器(GUI工具包的一部分)的浏览器中,并视觉检查关键字和字符串文字的颜色,以更轻松地查看是否存在语法错误。

http://dev.mysql.com/downloads/gui-tools/5.0.html


0

有几种可能性。如果您正在使用支持事务的InnoDB表,您可以在.sql文件开头简单地执行start transaction;,并在结尾处执行rollback;。MySQL将输出任何语法错误。

如果您正在测试UPDATEDELETE语句,可以在末尾添加LIMIT 0以防止这些查询进行任何数据库更改,同时仍然让MySQL检查语法。


2
脚本可能包含会导致隐式提交的语句。 - Bill Karwin
是的,这对于.sql文件的内容做了一些假设。 - Travis Beale

-3

只需运行它....

开始事务

运行它

回滚


运行它会给出答案,但有没有什么东西可以显示那个文件中的语法错误... - maxjackie
12
如果表是MyISAM类型,或者脚本运行隐式提交语句(例如DDL),或者脚本包含COMMIT语句,则无法回滚。 - Bill Karwin
1
@Bill Karwin,他们的问题非常简短,没有提到任何这方面的内容;-) - KM.
3
在语句前加上“EXPLAIN”会使该语句被解析并报告解析器错误,而不会改变数据或占用过多数据库资源。 - symcbean
不要在生产环境中运行此代码!某些语句隐式并立即提交。具体有很多种。请参考 https://mariadb.com/kb/en/library/sql-statements-that-cause-an-implicit-commit/ 以获取详细列表。 - Roel Van de Paar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接