我正在尝试更新使用Visual Studio 2012中的数据库项目(.sqlproj
)维护和部署的数据库。使用SQL Server Management Studio更容易,但在这种情况下,我必须使用DACPAC。
使用DACPAC将列更改为不可为空的正确方法是什么?没有数据丢失的风险?
将可空列添加到表中。现在我需要发布一个更新,将列设置为非null并设置默认值。由于表中有行,因此更新失败。有一个“允许数据丢失”的设置,但这不是我们的选项,此更新不应导致数据丢失。这是一个显示问题的简单示例:
CREATE TABLE [dbo].[Hello]
(
[Id] INT IDENTITY(100,1) NOT NULL PRIMARY KEY,
[HelloString] NVARCHAR(50) NULL ,
[Language] NCHAR(2) NOT NULL
)
现在发布该数据库并添加行,HelloString中至少有一行应为null。
将表格定义更改为:
CREATE TABLE [dbo].[Hello]
(
[Id] INT IDENTITY(100,1) NOT NULL PRIMARY KEY,
[HelloString] NVARCHAR(50) NOT NULL DEFAULT 'Hello' ,
[Language] NCHAR(2) NOT NULL
)
这不能发表。
错误:
检测到行。架构更新正在终止,因为可能会发生数据丢失。
接下来,我尝试添加预部署脚本以将所有NULL设置为“Hello”:
UPDATE Hello SET HelloString = 'Hello' WHERE HelloString IS NULL
此发布尝试也失败,但出现相同的错误。查看自动生成的发布脚本,很明显为什么,但这似乎是不正确的行为。
NOT NULL
更改评论中的建议(为了避免此问题,您必须为所有行添加此列的值)并不能解决此问题。
/*
The column HelloString on table [dbo].[Hello] must be changed from NULL to NOT NULL. If the table contains data, the ALTER script may not work. To avoid this issue, you must add values to this column for all rows or mark it as allowing NULL values, or enable the generation of smart-defaults as a deployment option.
*/
IF EXISTS (select top 1 1 from [dbo].[Hello])
RAISERROR (N'Rows were detected. The schema update is terminating because data loss might occur.', 16, 127) WITH NOWAIT
GO
PRINT N'Altering [dbo].[Hello]...';
GO
ALTER TABLE [dbo].[Hello] ALTER COLUMN [HelloString] NVARCHAR (50) NOT NULL;
GO
PRINT N'Creating Default Constraint on [dbo].[Hello]....';
GO
ALTER TABLE [dbo].[Hello]
ADD DEFAULT 'hello' FOR [HelloString];
在SQL Server 2012(v11.0.5343)中看到,SQL Server数据工具11.1.31009.1
答案 0 :(得分:6)
使用SSMS发布dacpac时,您无法访问从SqlPackage.exe或Visual Studio发布时可用的完整发布选项集。我建议使用SqlPackage.exe或Visual Studio进行发布,并启用“生成智能默认值(如果适用)”选项。对于SqlPackage.exe,您将运行如下命令:
"C:\Program Files (x86)\Microsoft SQL Server\120\DAC\bin\SqlPackage.exe" /a:publish /sf:"C:\MyDacpac.dacpac" /tcs:"Data Source=MYSERVER;Initial Catalog=MYDATABASE;Integrated Security=true" /p:GenerateSmartDefaults=true
对于Visual Studio,您需要在“高级发布选项”对话框中选中“生成智能默认值”选项。