首页 > 解决方案 > 由于缺少似乎存在的列,Visual Studio SQL Server 数据库未成功迁移

问题描述

几年前,我在 Visual Studio 中设置了一个项目以输出到 Azure SQL V12 数据库,并尝试sqlcmd与迁移脚本一起使用(我这样说也是为了指出在某一时刻一切正常,下面讨论的所有内容已投入生产)。

我的部署后脚本如下所示:

PRINT N'Starting post deployment';
:setvar WorkDirectory "F:\path\to\scripts"
PRINT N'Starting 1.01';
:r $(WorkDirectory)\1.01\Deployment.sql
PRINT N'Starting 1.02';
:r $(WorkDirectory)\1.02\Deployment.sql
PRINT N'Starting 1.03'; :r $(WorkDirectory)\1.03\Deployment103.sql
PRINT N'Starting 1.04'; :r $(WorkDirectory)\1.04\Deployment104.sql

在没有对项目进行任何更改(无论如何都不是有意识的)之后,我发现当我尝试调试/生成数据库并应用迁移脚本时,我收到一个错误,因为引用了一个不存在的列桌子。以下是Deployment104.sql文件中的违规部分:

IF NOT EXISTS (SELECT *
               FROM sys.columns 
               WHERE Name = N'MissingColumn'
                 AND Object_ID = Object_ID(N'TableA'))
BEGIN
    ALTER TABLE TableA 
        ADD MissingColumn INT NOT NULL
END
GO

IF NOT EXISTS (SELECT 1 
               FROM information_schema.Routines
               WHERE ROUTINE_NAME = 'LIST_CODES'
                 AND ROUTINE_TYPE = 'PROCEDURE' 
                 AND ROUTINE_SCHEMA = 'dbo' )
BEGIN;
    EXEC('CREATE PROCEDURE dbo.LIST_CODES as set nocount on;')
END
GO

ALTER PROCEDURE [dbo].LIST_CODES 
AS
    SELECT * 
    FROM CodesTable ct 
    LEFT JOIN TableA ta ON ct.CodeId = ta.CodeId
    WHERE ta.MissingColumn= 1999
    ORDER BY ct.CodeId
GO

Db 最终在此时部分创建。但是,当我运行第一次检查该列是否存在时,我实际上得到了一个条目,这意味着该列确实存在于 TableA 中。然而我在服务器资源管理器(VS 2019 预览版 16.4)中看不到它,显然脚本的下一部分也看不到它。

我做错了什么,和/或如何使脚本和数据库就哪些列存在而哪些不存在达成一致?

编辑:作为更新,在运行 PostDeploymentScript 失败时,运行有问题的脚本本身(在本例中为 Deployment104)工作得很好,之后列和存储过程都完全按照服务器资源管理器中的预期显示,并且可以通过其他查询。

标签: sql-servervisual-studiotsql

解决方案


我认为问题在于您正在尝试将非空列添加到现有表中。您需要添加一个默认值,例如 0 或使用支持 null 的数据类型。例如:

BEGIN
    alter table TableA 
    ADD MissingColumn int NOT NULL DEFAULT 0
END

在第二个 BEGIN 之后还有一个分号。

当前的:

IF NOT EXISTS ( SELECT  1 FROM information_schema.Routines
   WHERE ROUTINE_NAME = 'LIST_CODES'AND ROUTINE_TYPE = 'PROCEDURE' AND ROUTINE_SCHEMA = 'dbo' )
BEGIN;
    EXEC('CREATE PROCEDURE dbo.LIST_CODES as set nocount on;')
END
GO

固定的:

IF NOT EXISTS ( SELECT  1 FROM information_schema.Routines
   WHERE ROUTINE_NAME = 'LIST_CODES'AND ROUTINE_TYPE = 'PROCEDURE' AND ROUTINE_SCHEMA = 'dbo' )
BEGIN
    EXEC('CREATE PROCEDURE dbo.LIST_CODES as set nocount on;')
END
GO

在这些更改之后,我能够让语句在 sqlfiddle 中运行。这是链接http://sqlfiddle.com/#!18/51253/3


推荐阅读