【问题标题】:How can I programmatically check (parse) the validity of a TSQL statement?如何以编程方式检查(解析)SQL 语句的有效性?
【发布时间】: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

标签: c# .net sql-server tsql ado.net


【解决方案1】:

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

【讨论】:

【解决方案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 可以使用以下系统过程和函数解析您的语法、过程和表:

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

    【讨论】:

      猜你喜欢
      • 2020-12-19
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      相关资源
      最近更新 更多