Visual Studio 2013数据库项目删除列

40

在数据表中存在数据行的情况下,有人知道从数据库中删除现有列的最佳方法吗。

我尝试过的方法似乎不能正常工作。我在数据库项目中包含了一个预部署脚本,其中执行了一些操作。

GO
if exists(select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'Mercury.dbo.Discounts' and COLUMN_NAME = 'ColumnToRemove')
BEGIN
    ALTER TABLE Database.dbo.Table1 Drop Column ColumnToRemove
END
GO

然后在创建表的脚本中,我从“创建表脚本”中删除了有问题的列。

执行dacpac后,我收到以下反馈:

Initializing deployment (Start)
*** The column [dbo].[Table1].[ColumnToRemove] is being dropped, data loss could occur.
Initializing deployment (Complete)
Analyzing deployment plan (Start)
Analyzing deployment plan (Complete)
Updating database (Start)
An error occurred while the batch was being executed.
Updating database (Failed)
*** Could not deploy package.
Warning SQL72015: The column [dbo].[Table1].[ColumnToRemove] is being dropped, data loss could occur.
Error SQL72014: .Net SqlClient Data Provider: Msg 50000, Level 16, State 127, Line 6 Rows were detected. The schema update is terminating because data loss might occur.
Error SQL72045: Script execution error.  The executed script:
IF EXISTS (SELECT TOP 1 1
           FROM   [dbo].[Table1])
    RAISERROR (N'Rows were detected. The schema update is terminating because data loss might occur.', 16, 127)
        WITH NOWAIT;    

可能是重复的问题:允许(一次性)在数据库项目中删除列 - drneel
1
尝试取消选中“如果可能发生数据丢失,则阻止增量部署”选项,但仍然出现相同的错误。 - DRobertE
5个回答

53

我知道这是一个旧的帖子,但当我遇到同样的问题时,我偶然找到了这个帖子.. 或许仍有人会从中受益。

以下是对我有效的方法:

在VS中右键单击数据库项目时,会出现“发布数据库”对话框。您设置目标服务器连接并选择正确的数据库。

然后点击“高级...”按钮打开“高级发布设置”。

1) Uncheck - 'Block incremental deployment if data loss might occur' checkbox.
2) Check - 'DROP objects in target but not in project'

点击 OK 按钮。 然后点击 Generate Script 按钮以生成发布脚本。

如果您想经常生成脚本,则可以将这些设置保存到配置文件中。


如果只是需要删除一列,为什么我们需要指定#2呢?在我看来,#2是有风险的。 - SouravA
在VS2019中工作过。 - coder kemp

24

您需要修改数据库项目属性

  1. 进入项目属性
  2. 调试选项卡
  3. 取消勾选下列选项:“如果可能会发生数据丢失,则阻止增量部署”如下图所示


所以实际上可以从项目的属性和发布设置中控制此选项? - Jim Aho
当我试图将表 [dbo].[tblUsers] 中的列 vs_column 的类型从 NVARCHAR(5) 缩小到 NVARCHAR(3) 时,由于该列中包含了数据,我遇到了另一个问题或错误。目前该表中的列 vs_column 类型为 NVARCHAR(5) NULL,但正在被更改为 NVARCHAR(3) NULL。这可能会导致数据丢失。 - Saad Awan

4
如果由于项目相关原因无法取消“如果可能导致数据丢失,则阻止增量部署”,您可以编写一个预部署脚本和一个后部署脚本来启用转换。如果升级后的表中有任何列的依赖关系,这将比以下示例更加复杂。
例如预部署脚本:
IF EXISTS (SELECT *
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = 'YourSchema'
    AND TABLE_NAME = 'YourTable'
    AND COLUMN_NAME = 'ColumnToBeDropped')
BEGIN

    CREATE TABLE [Upgrade].[YourTable](
        [YourTableId] [int] NOT NULL,
        [KeepThisColumn] [money] NOT NULL)

    INSERT INTO Upgrade.YourTable
    (YourTableId, KeepThisColumn)
    SELECT YourTableId, KeepThisColumn
    FROM YourSchema.YourTable

    TRUNCATE TABLE YourSchema.YourTable

END

然后数据库项目将从您的数据库中删除要删除的列。您需要一个发布后脚本将数据传输回实际表格。以下是示例发布后脚本:
IF EXISTS (SELECT *
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = 'Upgrade'
    AND TABLE_NAME = 'YourTable')
BEGIN

    SET IDENTITY_INSERT YourSchema.YourTable ON

    INSERT INTO YourSchema.YourTable
    (YourTableId, KeepThisColumn)
    SELECT YourTableId, KeepThisColumn
    FROM Upgrade.YourTable

    SET IDENTITY_INSERT YourSchema.YourTable OFF

    DROP TABLE Upgrade.YourTable

END

4

在我的情况下...

使用Visual Studio 2015中的模式比较。在打开模式比较窗口后:

  1. 模式比较选项(菜单条中的小齿轮图标)。
  2. 转到“常规”选项卡。
  3. 取消选中可能导致数据丢失的阻止

在整个会话期间,此操作将保持未选中状态。我没有确认退出会话时是否仍然选中。


当我试图将nvarchar-5列的大小减小到nvarchar-3时,遇到了另一个问题或错误,并且该列中有数据。[dbo]。[tblUsers]表中vs_column列的类型当前为NVARCHAR(5)NULL,但正在更改为NVARCHAR (3)NULL。可能会发生数据丢失。 - Saad Awan

0

你只需要在项目中执行一次(而不是在预部署脚本中),并且在发布时,你需要选择“允许数据丢失”的选项进行操作。如果你删除了一个列,我看不到避免可能的数据丢失的方法。完成后,你可以随时将该设置更改回来。


好的,问题的一部分是列上放置的默认约束...我首先删除了它,然后删除了该列,这样就可以解决了。但是下一个问题是,如果它不是默认约束,而是其他类型的约束,有没有办法删除给定列上的所有约束? - DRobertE
我认为没有像重命名列那样轻松的方法来完成它。但是,如果您删除该列,则在同一数据库中存在依赖项时,项目的构建应完全失败。它们还应显示在错误/警告消息中。您可以双击这些消息以转到相应的文件,然后注释掉约束条件或删除其文件/文本。 - Peter Schott
不确定为什么要在预部署脚本中删除列。项目应该在发布时删除该列,但是因为已经删除了该列而无法找到它可能会让你感到困惑。执行此操作的脚本是在实际运行预/后部署脚本之前生成的;因此,在发布操作中将尝试在脚本中删除该列。尝试将“删除列”操作从预部署脚本中移除,并选择在发布时选择“生成脚本”,而不是直接推送更改。 - Peter Schott
将所有内容从预部署脚本中删除... 发布并选择针对我的目标数据库生成脚本... 在生成的脚本中,生成了以下行 IF EXISTS (select top 1 1 from [dbo].[Discounts]) RAISERROR (N'检测到行。模式更新正在终止,因为可能会发生数据丢失。', 16, 127) WITH NOWAIT - DRobertE
在表Discounts中有数据,我们试图删除表列,但是如果我有块增量更新而未检查数据丢失,则到底是什么生成了该行? - DRobertE
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接