如何在不执行脚本的情况下在 SQL 脚本上测试 SQLCMD

How to test SQLCMD on a SQL script without executing the script

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

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

的值

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

考虑的备选方案

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

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

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

SET NOEXEC ON 有一个重要的限制。该文档误导性地指出 "this setting is useful for having SQL Server validate the syntax and object names in Transact-SQL code when executing",但实际上,在 SET NOEXEC ON 下,SQL 服务器根本不会将名称解析为大多数对象。以下脚本将正确解析:

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

因此,如果您只想检查句法有效性,PARSEONLY 优于 NOEXEC