如何以编程方式检查(解析)SQL 语句的有效性?

Posted

技术标签:

【中文标题】如何以编程方式检查(解析)SQL 语句的有效性?【英文标题】:How can I programmatically check (parse) the validity of a TSQL statement? 【发布时间】:2011-03-06 06:59:42 【问题描述】:

我正在尝试使我的集成​​测试更具幂等性。一个想法是在每次测试后执行回滚,另一个想法是如何以编程方式解析文本,类似于查询分析器或 SSMS 中的绿色复选框。

如何让 SQL Server 解析我的命令而不使用 ADO.NET 运行它?

更新: 这就是最终如愿以偿的工作:

using (DbCommand executeOnly = Factory.DbCommand())

    executeOnly.Connection = command.Connection;
    executeOnly.CommandType = CommandType.Text;
    executeOnly.CommandText = "SET NOEXEC ON;" + sqlCommand;
    executeOnly.Connection.Open();
    executeOnly.ExecuteNonQuery();

//set more properties of command.
command.Execute();

由于莫名其妙的原因,“SET PARSEONLY ON”只在查询分析器中有效。我无法在 ADO.NET 连接上设置它。这也很好,因为PARSEONLY 似乎只捕获语法错误,这不是常见的错误。 SET NOEXEC ON 将捕获更多种类的错误,例如引用缺失表或列或存储过程中缺失参数的视图。

【问题讨论】:

我假设它是executeOnly.CommandText = "SET NOEXEC ON; " + sqlCommand; :3 【参考方案1】:

我认为您要查找的命令是SET NOEXEC ON。如果你为你的连接设置了这个,查询将被解析但不会被执行。另一种选择是SET PARSEONLY ON,但老实说,我不确定两者之间的真正区别是什么。

【讨论】:

+1, SET NOEXEC (Transact-SQL) 根据我的回答从 cmets 开始,我认为 SQL 2K8 中的 SET NOEXEC ON 可能存在错误 - 也已被其他人复制。查看我提出的 MS Connect 错误:connect.microsoft.com/SQLServer/feedback/details/569263/… PARSEONLY 只解析,NOEXEC 不执行但解析编译。即,在丢失的表等上抛出错误。【参考方案2】:

+1 埃里克的回答。但我发现SET FMTONLY ON 也很有用,因为SET NOEXEC ON 似乎不会抛出所有错误。

例如

SELECT * FROM ATableThatDoesNotExist

使用SET NOEXEC ON 运行它表示成功,尽管数据库中不存在该表。使用SET FMTONLY ON 运行它会抛出“无效的对象名称”错误。

SET FMTONLY ON 还返回有关将返回的结果集的元数据,这非常方便

【讨论】:

使用SET NOEXEC ONSELECT * FROM ATableThatDoesNotExist时出现错误 @KM @Ada 抱歉,我的SET NOEXEC ONSELECT 之间没有重要的“GO” 我没有使用 GO,我只是运行 SET NOEXEC ON 并收到 Command(s) completed successfully. 消息,然后运行查询,然后产生了错误。如果您运行SET NOEXEC ON;SELECT...,则不会出现错误。通过在 SRET 和 SELECT 之间对接 GO 会给出错误 @KM - 啊哈。对我来说,在 SQL Server 2008 RTM 上我从来没有得到错误。但是,当我在 SQL Server 2005 上尝试时,它的行为与您所说的一样,当您有 GO 语句时。您在哪里尝试 2005?行为发生了变化似乎很奇怪 +1 for SET FMTONLY ON 还返回有关结果集的元数据。这对于在不执行实际 SQL 语句的情况下进行故障排除非常有用,特别是对于 QA 环境中的开发人员 :)【参考方案3】:

SQL Server 2012 可以使用以下系统过程和函数解析您的语法、过程和表:

sp_describe_first_result_set (Transact-SQL) sp_describe_undeclared_parameters (Transact-SQL) sys.dm_exec_describe_first_result_set (Transact-SQL) sys.dm_exec_describe_first_result_set_for_object (Transact-SQL)

They are supposedly replacing "SET FMTONLY".

我已经对它们进行了测试,它们比“SET NOEXEC ON”和“SET PARSEONLY ON”好很多

示例:

不会抛出错误:

sp_describe_undeclared_parameters
    @tsql = N'SELECT object_id, name, type_desc FROM sys.indexes;'

会正确抛出错误(“SET NOEXEC”和“SET PARSEONLY”在这种情况下不会抛出错误):

sp_describe_undeclared_parameters 
  @tsql = N'SELECT object_id, name, type_desc FROM sys.indexes;SELECT object_id, name, type_desc FROM sys.NOTaTABLE;'

【讨论】:

【参考方案4】:

使用以下查询

SET PARSEONLY ON
--Your query here
SET PARSEONLY OFF

【讨论】:

与 set statistics time, io on 不同,您的示例仍然执行查询:SET PARSEONLY ON;选择“确定”;设置 PARSEONLY 关闭;我们必须在关闭它之前添加 go 吗?【参考方案5】:

SET PARSEONLY:检查每个 Transact-SQL 语句的语法并返回任何错误消息,而不编译或执行语句。

【讨论】:

这是 SSMS 在您按下绿色复选框时所做的事情。您可以在 SQL Profiler 中轻松看到它发生的情况。【参考方案6】:

实际上,这取决于测试的目的。

最可靠的方法是在每次测试后使用回滚,前提是您的语句适合这样做(重量不会太重而无法实现)。

我过去曾这样做过,并且很高兴收到运行时问题的通知,而我不会以其他任何方式发现这些问题。

【讨论】:

+1 - 我同意。真正执行语句并在之后进行回滚将是最可靠的测试方式。 +1: SET NOEXEC ON 仅检查查询是否有效。查询可以是有效的,但不能返回正确的结果。【参考方案7】:

VSTSDBPro 有一个可以通过编程方式访问的查询解析器:http://blogs.msdn.com/b/gertd/archive/2008/08/21/getting-to-the-crown-jewels.aspx

【讨论】:

以上是关于如何以编程方式检查(解析)SQL 语句的有效性?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式检查 .NET 中的有效删除(修改)或写入权限?

在 C# 中以编程方式检查字符串是不是包含有效的 C# 代码

如何以编程方式检查系统上是不是安装了 SQL Server Management Studio?

如何以编程方式为 Django 中的给定模型生成 CREATE TABLE SQL 语句?

如何在不运行实际查询的情况下检查 JDBC 语句的 SQL 语法?

代码规范