2015-08-19 22 views
6

我试图更新在Visual Studio 2012中使用数据库项目(.sqlproj)维护和部署的数据库。使用SQL更容易Server Management Studio,但在这种情况下,我必须使用DACPAC进行部署。我如何更新一个可空的列不可为空,在SQL Server中使用DACPAC

使用DACPAC将列更改为不可为空的正确方法是什么?使用DACPAC并且不会冒数据丢失的风险?

表中添加了一个可为空的列。现在我需要发布一个更新,将列设置为非空并设置默认值。由于表中有行,所以更新失败。有一个设置'允许数据丢失',但这不是我们的选择,此更新不应导致数据丢失。这里有一个简单的例子来说明这个问题:

CREATE TABLE [dbo].[Hello] 
(
    [Id] INT IDENTITY(100,1) NOT NULL PRIMARY KEY, 
    [HelloString] NVARCHAR(50) NULL , 
    [Language] NCHAR(2) NOT NULL 
) 

现在发布数据库,并添加行,至少一行应该有HelloString空。

更改表的定义是:

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 
) 

这不能公布。

错误:

Rows were detected. The schema update is terminating because data loss might occur.

接下来,我尝试添加一个预先部署脚本来设置所有NULL是“你好”:

UPDATE Hello SET HelloString = 'Hello' WHERE HelloString IS NULL 

此发布尝试也失败,与同错误。看着自动生成发布脚本很明显为什么,但这似乎是不正确的行为。

  1. 前的默认添加
  2. 脚本检查任何行,则应用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

你可以插入默认值到空字段然后做更新? –

+0

@HolmesIV我试图用预部署脚本来做到这一点,但我会尝试单独执行它,看看是否有所作为。谢谢! – mafue

回答

3

当发布使用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的情况下,你会检查在高级的生成智能默认选项发布选项设置对话框。

+0

'生成智能默认值'用于为没有定义默认值的列生成默认值。这不是这种情况,我为我的专栏定义了一个默认值。但是看看autogen'd SQL,我可以看到它在将列def更改为NOT NULL之后试图应用我的默认值,所以也许您的答案是一种解决方法。这是你的意思吗? – mafue

+0

是的。使用预部署脚本将空值替换为所需的值,您就可以找到正确的路径。将它与启用的“生成智能默认值”设置相结合,可以让您成功部署。还有一个替代方案,但它涉及编写[部署贡献者](https://msdn.microsoft.com/en-US/library/dn306642(v = vs.103).aspx),这是更有效的工作。 –

+0

这工作。它与我的预部署脚本完全相同,但它也(最重要的)从autogen'd脚本中删除坏行,该脚本会在有空行的情况下抛出(空值或空值)。 – mafue

相关问题