J'ai un projet SQL Server Data Tools (VS2012) qui est publié automatiquement pendant le processus de génération. Une colonne a été récemment mise à jour de int
vers decimal(18,4)
. À la suite de cette modification, la publication échoue avec l'erreur
(49,1): SQL72014: fournisseur de données .Net SqlClient: Msg 50000, niveau 16, état 127, ligne 6 Des lignes ont été détectées. La mise à jour du schéma se termine car une perte de données peut se produire. (44,0): SQL72045: Erreur d'exécution de script. Le script exécuté:/* Le type de la colonne QuantityReceived dans la table [dbo]. [Reconciliation_Receiving] est actuellement INT NOT NULL mais est changé en DECIMAL (18, 4) NOT NULL. Une perte de données pourrait se produire. * /
SI EXISTE (sélectionnez le top 1 1 dans [dbo]. [Reconciliation_Receiving]) RAISERROR (aucune ligne n'a été détectée. La mise à jour du schéma se termine car une perte de données peut se produire. ', 16, 127) WITH NOWAIT Une erreur s'est produite lors de la génération du lot en cours d'exécution.
Je comprends pourquoi Je reçois cette erreur et je sais qu'elle pourrait être résolue en désactivant l'indicateur "Bloquer le déploiement incrémentiel en cas de perte de données". Cependant, il y a une forte opposition à la désactivation de cette fonctionnalité, donc ce ne sera pas une solution acceptable.
La seule autre solution à laquelle je peux penser est la suivante:
Cela semble cependant horriblement maladroit et inefficace.
Y a-t-il une meilleure alternative?
J'ai été tenté de contourner ce drapeau également, mais je suis tombé du côté de vos collègues et essayez maintenant de traiter ces problèmes "correctement". La voie (légèrement) moins maladroite consiste à utiliser des scripts de pré et post-déploiement pour effectuer le travail avec un changement de nom.
En fonction de la nature de la cible, vous devrez bien sûr prendre soin de supprimer et de recréer les contraintes de clé étrangère.
Dans mon cas, je supprimais une colonne d'une table.
La solution fournie dans cette réponse n'a pas fonctionné pour moi, elle a abouti à un invalid object name
erreur lors de la publication.
J'ai constaté qu'il était nécessaire de copier les lignes de la table, de désactiver la vérification des contraintes et de supprimer les lignes dans un script de pré-déploiement, puis de recopier les lignes dans la table avec l'insertion d'identité activée dans le script de post-déploiement.
Dans Script.PreDeployment.sql:
-- copy and delete dbo.Table1
BEGIN TRY
IF (EXISTS (
SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'Table1_copy'))
BEGIN
PRINT 'Dropping Table1_copy'
DROP TABLE dbo.Table1_copy
END
PRINT 'Copying dbo.Table1'
SELECT @LastID = MAX(ID), @StartID = MIN(ID)
FROM dbo.Table1
SET @EndID = @StartID + 1000
SELECT *
INTO dbo.Table1_copy
FROM dbo.Table1
WHERE ID BETWEEN @StartID AND @EndId
SET @StartID = @EndID + 1
SET IDENTITY_INSERT dbo.Table1_copy ON
WHILE @StartID < @LastID
BEGIN
SET @EndID = @StartID + 1000
INSERT dbo.Table1_copy (ID, Column1, Column2, Column3)
SELECT ID, Column1, Column2, Column3
FROM dbo.Table1
WHERE ID BETWEEN @StartID AND @EndId
SET @StartID = @EndID + 1
END
SET IDENTITY_INSERT dbo.Table1_copy OFF
PRINT 'Copied dbo.Table1 to dbo.Table1_copy'
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
PRINT 'Deleting dbo.Table1'
WHILE EXISTS (SELECT 1 FROM dbo.Table1)
DELETE TOP(1000) FROM dbo.Table1
PRINT 'Deleted dbo.Table1'
PRINT 'SUCCESS: Copy and delete dbo.Table1'
END TRY
BEGIN CATCH
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
PRINT 'ERROR: Copy and delete dbo.Table1'
PRINT 'ERROR MESSAGE: ' + ERROR_MESSAGE()
END CATCH
GO
Dans Script.PostDeployment.sql
DECLARE @StartID BIGINT, @LastID BIGINT, @EndID BIGINT
-- populate dbo.Table1
BEGIN TRY
PRINT 'Populating dbo.Table1'
SET IDENTITY_INSERT dbo.Table1 ON
SELECT @LastID = MAX(ID)
FROM dbo.Table1_copy
WHILE @StartID < @LastID
BEGIN
SET @EndID = @StartID + 1000
INSERT dbo.Table1 (ID, Column1, Column2, Column3)
SELECT ID, Column1, Column2, Column3
FROM dbo.Table1
WHERE ID BETWEEN @StartID AND @EndId
SET @StartID = @EndID + 1
END
SET IDENTITY_INSERT dbo.Table1 OFF
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
PRINT 'SUCCESS: Populating dbo.Table1'
END TRY
BEGIN CATCH
SET IDENTITY_INSERT dbo.Table1 OFF
PRINT 'ERROR: Populating dbo.Table1'
PRINT 'ERROR MESSAGE: ' + ERROR_MESSAGE()
END CATCH
GO