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 le IDENTITYdébut à partir de la valeur la plus récente des lignes existantes.
Tout d'abord, quelques données de test pour jouer avec:
CREATE TABLE dbo.ident_test (
id int NOT NULL,
xyz varchar(10) NOT NULL,
CONSTRAINT PK_ident_test PRIMARY KEY CLUSTERED (id)
);
INSERT INTO dbo.ident_test (id, xyz)
VALUES (1, 'test'),
(2, 'test'),
(5, 'test'),
(6, 'test'),
(10, 'test'),
(18, 'test'),
(19, 'test'),
(20, 'test');
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 colonne xyzrepré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:
BEGIN TRANSACTION;
Maintenant, ajoutons une colonne de travail temporaire id_tempet définissons cette colonne sur les idvaleurs de la colonne existante :
ALTER TABLE dbo.ident_test ADD id_temp int NULL;
UPDATE dbo.ident_test SET id_temp=id;
Ensuite, nous devons supprimer la idcolonne existante (vous ne pouvez pas simplement "ajouter" un IDENTITYà une colonne existante, vous devez créer la colonne en tant que IDENTITY). La clé primaire doit également disparaître, car la colonne en dépend.
ALTER TABLE dbo.ident_test DROP CONSTRAINT PK_ident_test;
ALTER TABLE dbo.ident_test DROP COLUMN id;
... et ajoutez à nouveau la colonne, cette fois sous la forme d'un IDENTITY, avec la clé primaire:
ALTER TABLE dbo.ident_test ADD id int IDENTITY(1, 1) NOT NULL;
ALTER TABLE dbo.ident_test ADD CONSTRAINT PK_ident_test PRIMARY KEY CLUSTERED (id);
Voici où cela devient intéressant. Vous pouvez l'activer IDENTITY_INSERTsur la table, ce qui signifie que vous pouvez définir manuellement les valeurs d'une IDENTITYcolonne lorsque vous insérez de nouvelles lignes (sans mettre à jour les lignes existantes, cependant).
SET IDENTITY_INSERT dbo.ident_test ON;
Avec cet ensemble, DELETEtoutes les lignes de la table, mais les lignes que vous supprimez sont OUTPUTdirectement dans la même table - mais avec des valeurs spécifiques pour la idcolonne (à partir de la colonne de sauvegarde).
DELETE FROM dbo.ident_test
OUTPUT deleted.id_temp AS id, deleted.xyz
INTO dbo.ident_test (id, xyz);
Une fois terminé, éteignez IDENTITY_INSERTà nouveau.
SET IDENTITY_INSERT dbo.ident_test OFF;
Déposez la colonne temporaire que nous avons ajoutée:
ALTER TABLE dbo.ident_test DROP COLUMN id_temp;
Et enfin, réamorcez la IDENTITYcolonne, de sorte que l'enregistrement suivant idreprendra après le nombre existant le plus élevé dans la idcolonne:
DECLARE @maxid int;
SELECT @maxid=MAX(id) FROM dbo.ident_test;
DBCC CHECKIDENT ("dbo.ident_test", RESEED, @maxid)
En vérifiant le tableau d'exemple, le idnombre le plus élevé est 20.
SELECT * FROM dbo.ident_test;
Ajoutez une autre ligne et vérifiez sa nouvelle IDENTITY:
INSERT INTO dbo.ident_test (xyz) VALUES ('New row');
SELECT * FROM dbo.ident_test;
Dans l'exemple, la nouvelle ligne aura id=21. Enfin, si vous êtes satisfait, validez la transaction:
COMMIT 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 TRANSACTIONcar 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 .. INTOne 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 idcolonne 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 INSERTet DELETEsur 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:
- Créez la table vide, avec la
idcolonne en tant que IDENTITY,
- Set
IDENTITY_INSERT ONpour la table,
- Remplissez la table,
- Set
IDENTITY_INSERT OFF, et
- Ressuscitez l'identité.
IDENTITY?