使用 SQLCMD 执行发布脚本不返回

Posted

技术标签:

【中文标题】使用 SQLCMD 执行发布脚本不返回【英文标题】:Executing Publish Scripts with SQLCMD doesn't return 【发布时间】:2015-01-27 00:07:13 【问题描述】:

在 SQL Server 数据库项目 (Visual Studio 2013) 上运行由“发布”>“生成脚本”对话框生成的 SQL 脚本时遇到问题。

如果从 SQL Management Studio 以 SQLCMD 模式运行,生成的脚本执行良好,通常需要 2 到 10 秒。但是,如果使用 SQLCMD.exe(通过 CMD 或批处理文件)运行,它似乎会挂起并且永远不会完成。我猜 SQL Management Studio 正在使用一些附加参数(预设?)来执行脚本,但我无法让它直接与 SQLCMD 一起使用。生成的 SQL 脚本通常最多只有 200 行左右。这是我正在使用的命令(在 Windows Server 2012R2 上从批处理文件运行,以管理员身份运行):

"D:\Program Files\Microsoft SQL Server\110\Tools\Binn\SQLCMD.exe" -S SQLSERVER1 -i "D:\Database\MyDatabase.publish.sql"

我没有看到任何错误,但 SQLCMD 从未退出,提示我必须终止该进程。下面是发布对话框创建的脚本类型的示例:

/*
Deployment script for MyDatabase

This code was generated by a tool.
Changes to this file may cause incorrect behavior and will be lost if
the code is regenerated.
*/

GO
SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON;

SET NUMERIC_ROUNDABORT OFF;


GO
:setvar DatabaseName "MyDatabase"
:setvar DefaultFilePrefix "MyDatabase"
:setvar DefaultDataPath "D:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\"
:setvar DefaultLogPath "D:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\"

GO
:on error exit
GO
/*
Detect SQLCMD mode and disable script execution if SQLCMD mode is not supported.
To re-enable the script after enabling SQLCMD mode, execute the following:
SET NOEXEC OFF; 
*/
:setvar __IsSqlCmdEnabled "True"
GO
IF N'$(__IsSqlCmdEnabled)' NOT LIKE N'True'
    BEGIN
        PRINT N'SQLCMD mode must be enabled to successfully execute this script.';
        SET NOEXEC ON;
    END


GO
IF EXISTS (SELECT 1
           FROM   [master].[dbo].[sysdatabases]
           WHERE  [name] = N'$(DatabaseName)')
    BEGIN
        ALTER DATABASE [$(DatabaseName)]
            SET READ_COMMITTED_SNAPSHOT OFF;
    END


GO
IF EXISTS (SELECT 1
           FROM   [master].[dbo].[sysdatabases]
           WHERE  [name] = N'$(DatabaseName)')
    BEGIN
        ALTER DATABASE [$(DatabaseName)]
            SET PAGE_VERIFY NONE 
            WITH ROLLBACK IMMEDIATE;
    END


GO
USE [$(DatabaseName)];


GO
IF fulltextserviceproperty(N'IsFulltextInstalled') = 1
    EXECUTE sp_fulltext_database 'enable';


GO
PRINT N'Dropping FK_ORDR_BPO_ORDR_MASTER...';


GO
ALTER TABLE [dbo].[ORDR_BPO] DROP CONSTRAINT [FK_ORDR_BPO_ORDR_MASTER];


GO
PRINT N'Dropping FK_ORDR_CommonData_ORDR_MASTER...';


GO
ALTER TABLE [dbo].[ORDR_CommonData] DROP CONSTRAINT [FK_ORDR_CommonData_ORDR_MASTER];


GO
PRINT N'Dropping FK_ORDR_BPO_ProductType_ValuationProductCategory...';


GO
ALTER TABLE [dbo].[ORDR_BPO_ProductType] DROP CONSTRAINT [FK_ORDR_BPO_ProductType_ValuationProductCategory];


GO
PRINT N'Creating [dbo].[LOG_ServiceAction]...';


GO
CREATE TABLE [dbo].[LOG_ServiceAction] (
    [LOG_ServiceActionID] INT            IDENTITY (1, 1) NOT NULL,
    [ServiceActionName]   VARCHAR (255)  NOT NULL,
    [User_ID]             INT            NOT NULL,
    [TransactionID]       VARCHAR (32)   NOT NULL,
    [Message]             VARCHAR (1000) NOT NULL,
    [ActionDate]          DATETIME       NOT NULL,
    [FilePath]            VARCHAR (2000) NULL,
    [ExpiresDateUTC]      DATETIME       NOT NULL,
    CONSTRAINT [PK_LOG_ServiceAction] PRIMARY KEY CLUSTERED ([LOG_ServiceActionID] ASC)
);


GO
PRINT N'Creating FK_ORDR_BPO_ORDR_MASTER...';


GO
ALTER TABLE [dbo].[ORDR_BPO] WITH NOCHECK
    ADD CONSTRAINT [FK_ORDR_BPO_ORDR_MASTER] FOREIGN KEY ([MasterOrder_ID]) REFERENCES [dbo].[ORDR_MASTER] ([MasterOrder_ID]);


GO
PRINT N'Creating FK_ORDR_CommonData_ORDR_MASTER...';


GO
ALTER TABLE [dbo].[ORDR_CommonData] WITH NOCHECK
    ADD CONSTRAINT [FK_ORDR_CommonData_ORDR_MASTER] FOREIGN KEY ([MasterOrder_ID]) REFERENCES [dbo].[ORDR_MASTER] ([MasterOrder_ID]);


GO
PRINT N'Checking existing data against newly created constraints';


GO
USE [$(DatabaseName)];


GO
ALTER TABLE [dbo].[ORDR_BPO] WITH CHECK CHECK CONSTRAINT [FK_ORDR_BPO_ORDR_MASTER];

ALTER TABLE [dbo].[ORDR_CommonData] WITH CHECK CHECK CONSTRAINT [FK_ORDR_CommonData_ORDR_MASTER];


GO
PRINT N'Update complete.';


GO

对此的任何帮助将不胜感激,因为这是自动化部署过程的最后一个手动步骤。

更新:所以我有一些关于此的更多信息,可以帮助知道诊断此问题的人......我遇到的是发布脚本在开头设置变量,例如 DatabaseName(请参阅示例多于)。从 MS SQL Management Studio 以 SCLCMD 模式运行时,脚本有时永远不会返回。但是,如果我不是在 SQLCMD 模式下运行脚本,让它失败,然后在 SQLCMD 模式下重新运行它,它就会成功执行。

当脚本在 SQLCMD 模式下运行时无法返回时,我注意到有一些代码返回错误(不幸的是,我没有错误消息,但当我再次收到错误时我会更新):

IF EXISTS (SELECT 1
           FROM   [master].[dbo].[sysdatabases]
           WHERE  [name] = N'$(DatabaseName)')
    BEGIN
        ALTER DATABASE [$(DatabaseName)]
            SET READ_COMMITTED_SNAPSHOT OFF;
    END

脚本在 ALTER DATABASE [$(DatabaseName)] 命令上失败。我怀疑这与使用 SQLCMD.exe 从 CMD 行运行时出现的情况相同。我希望这会有所帮助,但我会继续寻找解决方案并在我这样做时编辑这篇文章。谢谢。

【问题讨论】:

【参考方案1】:

嗯.. 在研究了一段时间后,我终于找到了解决我的问题的方法(如果不是为什么它不起作用的答案)。

在从停止部署的数据库项目发布或生成数据库脚本期间有一个选项。如原始问题所述,ALTER DATABASE [$(DatabaseName)] 是罪魁祸首。

如果您在“发布数据库”对话框中,可以单击“高级...”按钮查看其他发布选项。取消选中“部署数据库属性”复选框将创建您的发布脚本,而没有 SQLCMD 一直挂起的初始 ALTER DATABASE 语句。

希望这有助于为其他人节省一些时间。干杯!

【讨论】:

【参考方案2】:

我也有类似的问题。

我对此部分发表了评论。

接下来,我指定了与数据库连接的数据库名称。 (从 MS SQL 服务器管理器工作室直接在楼上)

 And everything was done successfully. 
    --GO
    --IF N'$(__IsSqlCmdEnabled)' NOT LIKE N'True'
    --    BEGIN
    --        PRINT N'SQLCMD mode must be enabled to successfully execute this script.';
    --        SET NOEXEC ON;
    --    END

【讨论】:

以上是关于使用 SQLCMD 执行发布脚本不返回的主要内容,如果未能解决你的问题,请参考以下文章

如何使用sqlcmd在批处理脚本中执行SQL?

从WiX使用SQLCMD执行二进制SQL文件

SqlServer2008R2使用SQLCMD执行多个脚本

路径中的 SQLCMD 变量

使用SQLCMD在SQLServer执行多个脚本

使用SQLCMD在SQLServer执行多个脚本