J'ai créé une table dans une base de données qui existe déjà dans une autre base de données. Il a été initialement rempli avec les anciennes données DB. Le PK de la table devait recevoir les valeurs qui existent déjà dans ces enregistrements, il ne pouvait donc pas s'agir d'une auto-incrémentation.
Maintenant, j'ai besoin de la nouvelle table pour avoir son PK comme auto-incrémentation. Mais comment puis-je faire cela après que le PK existe déjà et ait des données?
IDENTITY
?Réponses:
La façon dont je comprends votre question est que vous avez une table existante avec une colonne qui jusqu'à présent était remplie de valeurs manuelles, et maintenant vous voulez (1) faire de cette colonne une
IDENTITY
colonne, et (2) vous assurer que leIDENTITY
début à partir de la valeur la plus récente des lignes existantes.Tout d'abord, quelques données de test pour jouer avec:
L'objectif est de faire de la colonne de clé primaire de la table
id
, unIDENTITY
colonne qui commencera à 21 pour le prochain enregistrement qui sera inséré. Pour cet exemple, la colonnexyz
représente toutes les autres colonnes de la table.Avant de faire quoi que ce soit, veuillez lire les avertissements au bas de cet article.
Tout d'abord, en cas de problème:
Maintenant, ajoutons une colonne de travail temporaire
id_temp
et définissons cette colonne sur lesid
valeurs de la colonne existante :Ensuite, nous devons supprimer la
id
colonne existante (vous ne pouvez pas simplement "ajouter" unIDENTITY
à une colonne existante, vous devez créer la colonne en tant queIDENTITY
). La clé primaire doit également disparaître, car la colonne en dépend.... et ajoutez à nouveau la colonne, cette fois sous la forme d'un
IDENTITY
, avec la clé primaire:Voici où cela devient intéressant. Vous pouvez l'activer
IDENTITY_INSERT
sur la table, ce qui signifie que vous pouvez définir manuellement les valeurs d'uneIDENTITY
colonne lorsque vous insérez de nouvelles lignes (sans mettre à jour les lignes existantes, cependant).Avec cet ensemble,
DELETE
toutes les lignes de la table, mais les lignes que vous supprimez sontOUTPUT
directement dans la même table - mais avec des valeurs spécifiques pour laid
colonne (à partir de la colonne de sauvegarde).Une fois terminé, éteignez
IDENTITY_INSERT
à nouveau.Déposez la colonne temporaire que nous avons ajoutée:
Et enfin, réamorcez la
IDENTITY
colonne, de sorte que l'enregistrement suivantid
reprendra après le nombre existant le plus élevé dans laid
colonne:En vérifiant le tableau d'exemple, le
id
nombre le plus élevé est 20.Ajoutez une autre ligne et vérifiez sa nouvelle
IDENTITY
:Dans l'exemple, la nouvelle ligne aura
id=21
. Enfin, si vous êtes satisfait, validez la transaction:Important
Ce n'est pas une opération banale, et elle comporte plusieurs risques dont vous devez être conscient.
Faites-le dans un environnement de test dédié. Avoir des sauvegardes. :)
J'aime utiliser
BEGIN/COMMIT TRANSACTION
car cela empêche d'autres processus de jouer avec la table pendant que vous êtes en train de la changer, et cela vous donne la possibilité de tout restaurer en cas de problème. Cependant, tout autre processus qui tente d'accéder à votre table avant d'avoir validé votre transaction finira par attendre. Cela peut être assez mauvais si vous avez une grande table et / ou si vous êtes dans un environnement de production.OUTPUT .. INTO
ne fonctionnera pas si votre table cible a des contraintes de clé étrangère ou l'une des nombreuses autres fonctionnalités dont je ne me souviens pas du haut de ma tête. Vous pouvez à la place décharger les données dans une table temporaire, puis les réinsérer dans la table d'origine. Vous pourrez peut-être utiliser la commutation de partition (même si vous n'utilisez pas de partitions).Exécutez ces instructions une par une, pas en tant que lot ou dans une procédure stockée.
Essayez de penser à d'autres choses qui peuvent dépendre de la
id
colonne que vous supprimez et recréez. Tous les index devront être supprimés et recréés (comme nous l'avons fait avec la clé primaire). N'oubliez pas de scripter chaque index et contrainte que vous devrez recréer au préalable.Désactivez les déclencheurs
INSERT
etDELETE
sur la table.Si la recréation de la table est une option:
Si la recréation de la table est une option pour vous, tout est beaucoup plus simple:
id
colonne en tant queIDENTITY
,IDENTITY_INSERT ON
pour la table,IDENTITY_INSERT OFF
, etla source
IDENTITY_INSERT ON
, le remplir et le désactiver. C'est ce que je voulais faire, mais je ne savais pas que MSSQL le supportait.L'utilisation de UPDATE, DELETE ou INSERT pour déplacer des données peut prendre beaucoup de temps et utiliser des ressources (IO) sur les données et les fichiers journaux / disques. Il est possible d'éviter de remplir le journal des transactions avec potentiellement beaucoup d'enregistrements tout en travaillant sur une grande table: à l'aide de la commutation de partition, seules les métadonnées sont modifiées.
Aucun mouvement de données n'est impliqué et ceci est donc effectué très rapidement (presque instantanément).
Exemple de table
La question n'affiche pas le tableau DDL d'origine. Le DDL suivant sera utilisé comme exemple dans cette réponse:
Une demi-douzaine d'identifiants aléatoires factices de 0 à 15 sont ajoutés à cette requête:
Exemple de données dans
IdT
Nouvelle table avec
IDENTITY(0, 1)
Le seul problème avec
idT
est le manque de laIDENTITY(0, 1)
propriété sur id. Une nouvelle table avec une structure similaireIDENTITY(0, 1)
est créée:Mis à part
IDENTITY(0, 1)
,idT_Switch
est identique àidT
.Clés étrangères
Les clés étrangères
idT
doivent être retirées pour permettre l'utilisation de cette technique.Commutateur de partition
Les tableaux
idT
etidT_Switch
ont une structure compatible. Au lieu d'utiliserDELETE
,UPDATE
et desINSERT
déclarations de déplacer des lignes deidT
laidT_Switch
ou suridT
lui - même,ALTER TABLE ... SWITCH
peut être utilisé:La «partition» unique de
PK_idT
(la table entière) est déplacée versPK_idT_Switch
(et vice versa).idT
contient maintenant 0 lignes etidT_Switch
contient 6 lignes.Vous pouvez trouver la liste complète des exigences de compatibilité source et destination ici:
Transfert efficace des données à l'aide de la commutation de partition
Notez que cette utilisation de
SWITCH
ne nécessite pas Enterprise Edition, car il n'y a pas de partitionnement explicite. Une table non partitionnée est considérée comme une table avec une seule partition à partir de SQL Server 2005.Remplacer
idT
idT
est maintenant vide et inutile et peut être supprimé:idT_Switch
peut être renommé et remplacera l'ancienneidT
table:Clés étrangères
Les clés étrangères peuvent être ajoutées à nouveau à la nouvelle
idT
table. Tout autre élément précédemment suppriméidT
pour rendre les tables compatibles pour la commutation devra également être refait.Réensemencer
Cette commande renvoie 0. La table idT contient 6 lignes avec MAX (id) = 15. DBCC CHECKIDENT (nom_table) peut être utilisé:
Parce que 15 est plus grand que 0, il se réamorcera automatiquement sans chercher MAX (id):
IDENT_CURRENT renvoie désormais 15 .
Testez et ajoutez des données
Une
INSERT
déclaration simple :Ajoute cette ligne:
La
id
colonne utilise maintenant l'identité et la nouvelle valeur insérée est en effet 16 (15 + 1).Plus d'information
Il y a une question et une réponse connexes avec plus d'informations sur la
SWITCH
technique ici:Pourquoi la suppression de la propriété d'identité sur une colonne n'est pas prise en charge
la source
Si vous souhaitez commencer avec une nouvelle valeur d'identité, vous devez réamorcer votre identité. Jetez un œil à la documentation de
CHECKIDENT
la source
ACTIVER et DÉSACTIVER IDENTITY_INSERT
Si votre table est TABLE_A alors
la source