在这篇文章中,我们将了解2种不同的SQL语法检查工具,它们可以帮助在不执行查询的情况下发现查询的语法错误。
什么是SQL语法检查器?
SQL语法检查器工具可以验证SQL语法或指出不正确的语法错误,如果它存在的话。这些工具可以在不执行整个查询的情况下帮助确定语法错误。以下2个工具可以用来验证我们的T-SQL查询的语法。
- [SQL Server Management Studio (SSMS]
- [SQL Fiddle]
什么是SQL Server中的查询解析?
当我们在SQL Server中提交一个查询来执行时,它在执行查询的过程中会执行3个基本阶段。
- 剖析:在这个阶段,查询解析器检查和验证SQL语句的语法,并生成查询的解析树。解析树被发送到下一个阶段进行处理。
- 编译: 在这个 阶段,查询优化器为查询生成一个执行计划。
- 执行: 在这个最后阶段,存储引擎执行SQL语句。
如何用SQL Server Management Studio (SSMS)验证查询语法
SQL Server Management Studio(SSMS)是一个先进的集成开发工具,用于管理、治理和配置SQL Server,它还提供了一个查询编辑器选项来开发和执行T-SQL查询。我们可以在SSMS的查询编辑器工具栏上找到一个解析按钮,它只检查所选语句或用户给出的所有语句的语法。这样,我们就可以把SSMS作为一个SQL语法检查工具。
在这里,我们需要考虑到,当我们解析一个查询时,并不执行编译和执行阶段。在下面的例子中,我们将检查一个非常简单的查询的语法。验证一个查询的语法只包括两个简单的步骤。
- 将查询粘贴或写入查询面板中
- 点击解析按钮或按Control+F5组合键
如图所示,查询的语法已经被成功验证。现在我们将删除语句中的FROM子句并重新解析查询。
在对查询进行重新解析后,SQL Server返回一个不正确的语法错误。检查查询语法的另一个选择是使用SET PARSE ONLY命令。该命令将会话配置为解析模式。
SET PARSEONLY ON
GO
SELECT FirstName,
MiddleName,LastName
FROM Person.Person
SQL Fiddle
SQL Fiddle是一个在线网络应用,可以用来练习或分享不同数据库系统的查询及其模式构建脚本。
除此之外,我们可以把SQL Fiddle作为一个SQL语法检查器,但我们需要创建所有放在查询中的对象。例如在这个示例查询中,我们可以建立模式并执行查询。
同时,它显示了查询执行后的执行计划。
如何编译不执行的查询。SET NOEXEC ON命令
为一个会话启用NOEXEC选项后,SQL Server会解析和编译查询的每条语句,但它不会执行查询。这个命令的好处是执行解析和编译阶段。NOEXEC选项提供了延迟的名称解析,所以它只控制被引用的对象,如果批处理中的一个或多个被引用的对象不存在,将不会抛出错误。我们将用一个非常简单的例子来解释这个概念。在这个例子的查询中,一切都很好,因为表和列都存在,语法也是有效的
SET NOEXEC ON
GO
SELECT FirstName,
MiddleName,LastName
FROM Person.Person
GROUP BY FirstName,
MiddleName,LastName
在下面的例子中,表并不存在,但是查询被验证了,但是没有被编译。
SELECT FirstName,
MiddleName,LastName
FROM Person.Person_NotExist
GROUP BY FirstName,
MiddleName,LastName
在这最后一个例子中,SQL Server没有找到被引用的对象,所以它将返回一个错误。
SET NOEXEC ON
GO
SELECT FirstName1,dbo.NotExistsFunction,
MiddleName,LastName
FROM Person.Person
GROUP BY FirstName,
MiddleName,LastName
当我们只解析下面的查询时,结果将成功返回,但由于group by后面缺少列名,查询的语法是无效的。
SELECT FirstName,
MiddleName,LastName
FROM Person.Person
GROUP BY MiddleName
尽管如此,在启用SET NOEXEC选项后,查询结果将返回一个错误。
这个例子显示了NOEXEC和PARSEONLY选项的区别。当我们纠正了错误的语法拼写后,SQL Server并没有返回任何错误。
SET NOEXEC ON
GO
SELECT FirstName,
MiddleName,LastName
FROM Person.Person
GROUP BY FirstName,
MiddleName,LastName
关于SET NOEXEC命令的另一个关键点是与缓存的执行计划有关。SQL Server将执行的查询的执行计划存储在计划缓存中。当我们在启用NOEXEC选项后执行一个查询,如果这个查询没有返回任何错误,那么这个查询的执行计划将被存储在计划缓存中。让我们通过一个例子来看看这个工作机制。首先,我们将清除例子中查询的计划缓存数据(如果它存在)。要做到这一点,我们将执行下面的查询并找到计划缓存的细节。
SELECT *
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE usecounts > 0 AND
text like '%SELECT FirstName,
MiddleName,LastName
FROM%' AND text NOT LIKE '%sys.dm_exec_cached_plans%'
ORDER BY usecounts DESC;
作为第二步,我们将放弃存储在样本查询中的执行计划。我们将把计划处理数据作为一个参数传递给DBCC FREEPROCCACHE。
DBCC FREEPROCCACHE(0x06001200A94F9D0C203F93A87B02000001000000000000000000000000000000000000000000000000000000)
在执行查询之前,我们可以创建一个扩展事件会话来观察查询编译事件。这个扩展事件必须包括query_pre_execution_showplan。这个事件可以捕捉到SQL语句被编译的情况。同时,这个事件以XML格式显示执行计划。
SET NOEXEC ON
GO
SELECT FirstName,
MiddleName,LastName
FROM Person.Person
GROUP BY FirstName,
MiddleName,LastName
正如我们所解释的,在启用NOEXEC命令后,该查询被查询优化器编译了。
总结
在这篇文章中,我们研究了两种不同的SQL语法检查工具,以验证我们的查询而不执行它们。