2016-11-25 1 views
0

J'ai actuellement une table, Messages. La colonne ID est la clé primaire et est remplie à l'aide d'une identité.Remplacer la clé primaire Identité avec séquence commençant par la prochaine valeur AUTO_INCREMENT

x-----------------------------x 
| ID  | Contents  | 
x-------------|---------------x 
| 1  || 
| 2  | 56789  | 
x-----------------------------x 

Je veux enlever l'identité sur la colonne ID et le remplacer par peuplant la valeur par défaut de ID d'une séquence, Messages_ID_Sequence.

Ceci est assez facile à accomplir en SSDT. Cependant, quand je Déployez le projet de base de données, la première valeur Messages_ID_Sequence est 1. Il est évident pourquoi quand je regarde le SQL généré pour Messages_ID_Sequence:

CREATE SEQUENCE [dbo].[CommandMsgs_MSGID_Sequence] 
    AS BIGINT 
    START WITH 1 
    INCREMENT BY 1 
    NO MAXVALUE 
    NO CYCLE 
    CACHE 10 

Le problème se produit lorsque je tente d'insérer un nouvel enregistrement du message. La première valeur de la séquence, 1, remplit la colonne ID du nouvel enregistrement et provoque une violation de la contrainte de clé primaire.

Alors comment puis-je m'assurer que lorsque Messages_ID_Sequence est créé, il commence à ID suivant que l'identité aurait fourni? Le script de création d'Action de construction sur Messages_ID_Sequence doit être défini sur Construire afin que la solution ne puisse pas impliquer quoi que ce soit que SSDT ne comprend pas.

Répondre

1

Vous pouvez construire dinamiquement la phrase SQL pour créer votre séquence, de sorte qu'elle commence à votre dernière identité. Ou mettre à jour à tout moment votre séquence afin qu'elle commence à la valeur désirée

/* Read the last identity value */ 
DECLARE @value bigint; 
select @value = max(id_field) from my_table; 

/* Create the sequence starting at that value */ 
DECLARE @sql nvarchar(max); 
SET @sql = N'CREATE SEQUENCE [dbo].[CommandMsgs_MSGID_Sequence] AS BIGINT START WITH ' + cast(@value as nvarchar(20)) + ' INCREMENT BY 1 NO MAXVALUE NO CYCLE CACHE 10;'; 
EXEC SP_EXECUTESQL @sql; 

/* Read the last identity value */ 
DECLARE @value bigint; 
select @value = max(id_field) from my_table; 

/* Create the sequence starting at that value */ 
DECLARE @sql nvarchar(max); 
SET @sql = N'ALTER SEQUENCE StreamEntrySequence RESTART WITH ' + cast(@value as nvarchar(20)) + ';'; 
EXEC SP_EXECUTESQL @sql; 
+0

Quand est-ce que j'exécuterais ceci? En tant que script de post-déploiement? S'il est ajouté dans mes scripts de post-déploiement, il s'exécutera chaque fois que je publie la base de données. Il ne semble pas que cela serait nécessairement nuisible, mais c'est un gaspillage étant donné que cela ne doit être fait qu'une seule fois par environnement. –

+0

Vous pouvez l'exécuter sur votre script de déploiement, juste après la création de la séquence. –

+0

J'ai mis à jour la réponse et maintenant, elle crée directement la séquence, vous n'avez donc besoin de l'appeler qu'une seule fois lorsque vous mettez à jour votre base de données. –