我有一个在构建过程中自动发布的 SQL Server Data Tools (VS2012) 项目。列最近从 更新int
到decimal(18,4)
。由于此更改,发布失败并出现错误
(49,1):SQL72014:.Net SqlClient 数据提供程序:检测到消息 50000、级别 16、状态 127、第 6 行。架构更新正在终止,因为可能会发生数据丢失。(44,0):SQL72045:脚本执行错误。执行的脚本: /* 表 [dbo].[Reconciliation_Receiving] 中列 QuantityReceived 的类型当前为 INT NOT NULL,但正在更改为 DECIMAL (18, 4) NOT NULL。可能会发生数据丢失。*/
IF EXISTS (select top 1 1 from [dbo].[Reconciliation_Receiving]) RAISERROR (N'Rows were detected. 由于可能发生数据丢失,架构更新正在终止。', 16, 127) WITH NOWAIT 批处理时发生错误被执行。
我了解我收到该错误的原因,并且我知道可以通过禁用“如果可能发生数据丢失,阻止增量部署”标志来解决它。但是,对于禁用该功能有非常强烈的反对意见,因此这不是一个可以接受的解决方案。
我能想到的唯一其他解决方案是执行以下操作:
- 制作一个临时表并将现有表的内容复制到临时表中
- 截断现有表
- 让 SSDT 更新数据类型
- 从临时表填回数据
不过,这似乎非常笨拙且效率低下。
有更好的选择吗?
我也很想绕过该标志,但已经站在您的同事一边,现在尝试“正确”处理这些问题。(稍微)不太笨重的路线是使用部署前和部署后脚本来完成重命名工作。
根据目标的性质,您当然可能需要处理删除和重新创建外键约束。
就我而言,我正在从表中删除一列。
此答案中提供的解决方案对我不起作用,导致
invalid object name
发布期间出现错误。我发现有必要从表中复制行,禁用约束检查并删除预部署脚本中的行,然后将行复制回表中,并在部署后脚本中启用身份插入。
在 Script.PreDeployment.sql 中:
在 Script.PostDeployment.sql 中
ALTER TABLE table_1 ALTER COLUMN [a] 十进制 (18,2)
在这种情况下将完成这项工作,预部署脚本的解决方案要简单得多。我还发现在发布之前更改目标将避免引发数据丢失错误。
有时 SSDT 会识别 ALTER TABLE/ALTER COLUMN 解决方案并在构建中使用它们,但我不知道从用户的角度来看如何使其可靠的规则。我不知道为什么它在这种情况下不使用它。使用 ALTER COLUMN 不会丢失数据。