【问题标题】:How to test SQLCMD on a SQL script without executing the script如何在不执行脚本的情况下在 SQL 脚本上测试 SQLCMD
【发布时间】:2017-03-02 16:36:24
【问题描述】:

我有一个大型 SQLCMD 语法的 SQL 脚本存储库。每个脚本定义了 0 个或多个 $(SomeParam)。我们有一个实用程序,它执行脚本并传递$(params) 的值,基本上使我们能够为各种数据模型配置和自动化构建。

有时我们的构建过程会失败,因为脚本指定了$(param),但我们的实用程序中没有配置。即我们对这个$(param) 集没有价值

我想在执行这些脚本之前对其进行测试。测试运行应确保已将所有必需的$(params) 提供给脚本。 SQL 本身不应该被执行——我只想知道它是否可以编译。这可以使用sqlcmd实现吗?

考虑的替代方案

我考虑了一种替代方法,即使用 Powershell 脚本查找文件中所有 $(param) 的匹配项(使用 RegEx),并对照实用程序中的参数列表进行交叉检查。如果可能的话,我希望在 sqlcmd 命令行或 SQL 脚本本身中保留所有功能。

【问题讨论】:

  • 可能是SET NOEXEC ON的工作。
  • 您能否提供一个额外的默认参数来指示它在测试模式下运行。然后使用这个标志只执行它不处于测试模式时包含的代码?这是我以前用来验证脚本而不运行的非常肮脏的解决方案。
  • @JeroenMostert - 我认为这可能是最好的方法。如果您可以将答案扩展一点,那么我会将其标记为正确答案。

标签: sql-server powershell sqlcmd


【解决方案1】:

SET NOEXEC ON 使 SQL Server 进入解析和编译语句但不执行语句的模式,但命令 SET NOEXEC OFF 除外,它会将事物恢复到原始状态。因此,如果语句由于缺少参数而在语法上无效,SET NOEXEC ON 将捕获它。

SET NOEXEC ON 有一个重要的限制。该文档误导性地指出“此设置对于让 SQL Server 在执行时验证 Transact-SQL 代码中的语法和对象名称很有用”,但事实上,在SET NOEXEC ON 下,SQL Server 根本不会将名称解析为大多数对象.以下脚本将无错误地解析:

SET NOEXEC ON;
GO
CREATE TABLE Foo(ID INT PRIMARY KEY);
GO
INSERT Fooo(ID) VALUES (5);  -- Oops, typo

这并不意味着根本没有解析任何名称。以下脚本仍然会失败:

SET NOEXEC OFF;
GO
CREATE FUNCTION Foo() RETURNS TABLE AS RETURN (SELECT 0 Bar);
GO
SET NOEXEC ON;
GO
SELECT dbo.Foo();  -- No error here, even though Foo can't be invoked this way
SELECT * FROM dbo.Foo(5);  -- Error here: too many arguments specified

很公平,你可能会说,但是:

SET NOEXEC ON;
GO
CREATE FUNCTION Foo() RETURNS TABLE AS RETURN (SELECT 0 Bar);
GO
SELECT * FROM dbo.Foo(5);  -- No error, because Foo doesn't exist

所以SET NOEXEC ON 既不能作为保证脚本完全有效的方法,也不能作为确定脚本绝对无效的方法。只要您意识到它的局限性,它仍然很有用。

就对象名称而言,确实还有另一个设置可以始终如一地工作:SET PARSEONLY ON。这不仅不执行语句,甚至不编译它们。上面给出NOEXEC 错误的示例将不会给出PARSEONLY 错误。如下所示:

CREATE TYPE MyInt FROM INT;
GO
CREATE TABLE A(ID MyInt);  
  -- Error under NOEXEC since MyInt does not exist, no error under PARSEONLY

因此,如果您只想检查语法有效性,PARSEONLYNOEXEC 更好。

【讨论】:

    【解决方案2】:

    您可以创建脚本的副本,将脚本的执行自动封装到 Transaction 中,并在脚本末尾引入错误。它总是打印错误。如果错误是您引入的错误,则脚本运行完美,否则打印参数错误。对不起我的英语

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2015-06-12
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多