Comment puis-je mettre à jour une colonne nullable pour ne pas être nullable, dans SQL Server utilisant DACPAC

J'essaie de mettre à jour une database gérée et déployée à l'aide d'un projet de database ( .sqlproj ) dans Visual Studio 2012. Cela est plus facile avec SQL Server Management Studio, mais dans ce cas je dois déployer à l'aide d'un DACPAC.

Quelle est la bonne façon de changer une colonne pour qu'elle ne soit pas NULL, en utilisant DACPAC et sans risquer de perdre des données?

Une colonne nullable a été ajoutée à une table. Maintenant, j'ai besoin de publier une mise à jour qui définit la colonne à null et définit une valeur par défaut. Parce qu'il y a des lignes dans la table, la mise à jour échoue. Il existe un paramètre permettant de 'permettre la perte de données' mais ce n'est pas une option pour nous et cette mise à jour ne devrait pas entraîner de perte de données. Voici un exemple simple qui montre le problème:

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

Publiez maintenant cette database et ajoutez des lignes, au less une ligne doit avoir une valeur null pour HelloSsortingng.

Modifier la définition de la table pour être:

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

Cela ne peut pas être publié.

Erreur:

Les lignes ont été détectées. La mise à jour du schéma se termine car une perte de données peut se produire.

Ensuite, j'ai essayé d'append un script de pré-deployment pour mettre tout NULL à 'Hello':

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

Cette tentative de publication échoue également, avec la même erreur. En regardant le script de publication généré automatiquement, il est clair pourquoi, mais cela semble être un comportement incorrect.

  1. L'altération NOT NULL est appliquée AVANT que la valeur par défaut ne soit ajoutée
  2. Le script search toutes les lignes, peu importe s'il y a des valeurs nulles ou non.

Le conseil dans le commentaire (Pour éviter ce problème, vous devez append des valeurs à cette colonne pour toutes les lignes) ne résout pas cela.

 /* The column HelloSsortingng 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 [HelloSsortingng] NVARCHAR (50) NOT NULL; GO PRINT N'Creating Default Constraint on [dbo].[Hello]....'; GO ALTER TABLE [dbo].[Hello] ADD DEFAULT 'hello' FOR [HelloSsortingng]; 

Vu dans SQL Server 2012 (v11.0.5343), devises de données SQL Server 11.1.31009.1

Lors de la publication d'un dacpac à l'aide de SSMS, vous n'avez pas access à l'set des options de publication disponibles lors de la publication à partir de SqlPackage.exe ou de Visual Studio. Je suggère de publier avec SqlPackage.exe ou avec Visual Studio et en activant l'option "Générer les valeurs par défaut intelligentes, le cas échéant". Dans le cas de SqlPackage.exe, vous devez exécuter une command comme:

 "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 

Dans le cas de Visual Studio, vous cochez l'option Générer les valeurs par défaut intelligentes dans la boîte de dialog Options de publication avancées.