150 votes

SQL Server - Supprimer l'identité d'une colonne dans une table

Nous avons une table de 5 Go (près de 500 millions de lignes) et nous voulons supprimer la propriété d'identité sur l'une des colonnes, mais lorsque nous essayons de le faire par SSMS - il s'arrête.

Cela peut-il être fait par T-SQL ?

Nous utilisons SQL Server 2005 Enterprise Edition

1 votes

Pouvez-vous afficher le schéma de la table ici ?

1 votes

Je suis sûr qu'il y a d'excellentes raisons pour que SQL Server ne prenne pas en charge la suppression d'une propriété d'identité d'une colonne via une simple instruction ALTER TABLE ..., mais cela me rend néanmoins triste actuellement que ce soit le cas.

161voto

Adam Wenger Points 9754

Vous ne pouvez pas supprimer un IDENTITY une fois qu'elle a été fixée.

Pour supprimer la colonne entière :

ALTER TABLE yourTable
DROP COLUMN yourCOlumn;

Informations sur ALTER TABLE ici

Si vous devez conserver les données, mais supprimer l'option IDENTITY colonne, vous devrez :

  • Créer une nouvelle colonne
  • Transférer les données de l'existant IDENTITY vers la nouvelle colonne
  • Abandonner l'existant IDENTITY colonne.

4 votes

Vous pouvez supprimer une spécification d'identité. En fait, j'ai dû le faire hier en utilisant SSMS, mais pas sur 500 millions de lignes.

39 votes

@simon si vous script vos changements, vous verrez que SSMS crée en fait une copie de la table sans la propriété identité.

4 votes

Je veux juste ajouter de renommer la nouvelle colonne au nom de la colonne originale. En outre, si cette identity est utilisée dans le cadre d'un foreign key dans une autre table, vous devrez d'abord supprimer les contraintes, puis prendre les mesures mentionnées par @AdamWenger pour supprimer l'identité. attribute/property Vous pouvez également consulter ce lien pour plus de détails sur la suppression de l'attribut uniquement : blog.sqlauthority.com/2009/05/03/ Bonne chance !

134voto

Mark Sowul Points 4249

Magic avec fonctionnalité de partitionnement (mais comme aucune partition n'est utilisée, vous n'avez pas besoin de l'édition Enterprise) :

  1. Supprimer toutes les clés étrangères qui pointent vers cette table
  2. script la table à créer ; renommez tout, par exemple 'MaTable2', 'MonIndex2', etc. Supprimez la spécification IDENTITY.
  3. Vous devriez maintenant avoir deux tables "identiques", l'une pleine, l'autre vide, sans IDENTITÉ.
  4. Exécuter ALTER TABLE [Original] SWITCH TO [Original2]
  5. Maintenant, votre table originale sera vide et la nouvelle table contiendra les données. Vous avez échangé les métadonnées des deux tables (instant).
  6. Abandonnez la table originale (maintenant vide), exec sys.sp_rename pour renommer les différents objets du schéma aux noms d'origine, puis vous pouvez recréer vos clés étrangères.

Par exemple, étant donné :

CREATE TABLE Original
(
  Id INT IDENTITY PRIMARY KEY
, Value NVARCHAR(300)
);
CREATE NONCLUSTERED INDEX IX_Original_Value ON Original (Value);

INSERT INTO Original
SELECT 'abcd'
UNION ALL 
SELECT 'defg';

Vous pouvez procéder comme suit :

--create new table with no IDENTITY
CREATE TABLE Original2
(
  Id INT PRIMARY KEY
, Value NVARCHAR(300)
);
CREATE NONCLUSTERED INDEX IX_Original_Value2 ON Original2 (Value);

--data before switch
SELECT 'Original', *
FROM Original
UNION ALL
SELECT 'Original2', *
FROM Original2;

ALTER TABLE Original SWITCH TO Original2;

--data after switch
SELECT 'Original', *
FROM Original
UNION ALL
SELECT 'Original2', *
FROM Original2;

--clean up
DROP TABLE Original;
EXEC sys.sp_rename 'Original2.IX_Original_Value2', 'IX_Original_Value', 'INDEX';
EXEC sys.sp_rename 'Original2', 'Original', 'OBJECT';

UPDATE Original
SET Id = Id + 1;

SELECT *
FROM Original;

0 votes

Je n'ai pas le temps d'essayer, mais c'est une bonne chose à savoir la prochaine fois que j'aurai vraiment besoin d'abandonner une identité.

17 votes

Cela devrait être la réponse acceptée. C'est le seul moyen réel de supprimer une colonne d'identité sans migration massive des données.

0 votes

Wow ! C'est très ingénieux.

63voto

Briguy37 Points 4748

Cela devient compliqué avec les contraintes de clés étrangères et primaires. Voici donc quelques scripts pour vous aider dans votre démarche :

Tout d'abord, créez une colonne dupliquée avec un nom temporaire :

alter table yourTable add tempId int NOT NULL default -1;
update yourTable set tempId = id;

Ensuite, obtenez le nom de votre contrainte de clé primaire :

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable';

Essayez maintenant de supprimer la contrainte de clé primaire pour votre colonne :

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;

Si vous avez des clés étrangères, cela va échouer, donc si c'est le cas, laissez tomber les contraintes de clés étrangères. GARDEZ LA TRACE DES TABLES POUR LESQUELLES VOUS EXÉCUTEZ CETTE OPÉRATION AFIN DE POUVOIR RAJOUTER LES CONTRAINTES PLUS TARD !!!

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable';
alter table otherTable drop constraint fk_otherTable_yourTable;
commit;
..

Une fois que toutes vos contraintes de clé étrangère ont été supprimées, vous pourrez supprimer la contrainte PK, abandonner cette colonne, renommer votre colonne temporaire et ajouter la contrainte PK à cette colonne :

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;
alter table yourTable drop column id;
EXEC sp_rename 'yourTable.tempId', 'id', 'COLUMN';
ALTER TABLE yourTable ADD CONSTRAINT PK_yourTable_id PRIMARY KEY (id) 
commit;

Enfin, ajoutez à nouveau les contraintes du FK :

alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id);
..

El Fin !

0 votes

Faites attention à la version de votre serveur sql, j'ai essayé dans le serveur sql azur, toutes les opérations ici ne sont pas supportées dans la version sql azur.

0 votes

Merci pour la réponse ! Elle m'a beaucoup aidé ! Vous devriez juste ajouter une vérification pour les index qui font référence à la colonne. Quelque chose comme : Select t.name 'Table', i.name 'Index', c.name 'Column', i.is_primary_key, i.is_unique From sys.tables t Inner Join sys.indexes i On i.object_id = t.object_id Inner Join sys.index_columns ic ON ic.object_id = i.object_id And i.index_id = ic.index_id Inner Join sys.columns c ON ic.object_id = c.object_id and ic.column_id = c.column_id Where t.name = 'tableName' Order By t.name, i.name, i.index_id, ic.index_column_id

0 votes

Bonne astuce, m'a beaucoup aidé, mais un point, je veux mentionner ici est que, Lorsque nous ajoutons une nouvelle colonne en double comme mentionné dans la 1ère étape, il a ajouté à la fin, mais généralement, nous voulons que notre clé primaire colonne c.-à-d. Id pour être la 1ère colonne dans cette table. Y a-t-il un moyen de contourner ce problème ?

22voto

liberty_ Points 221

Je viens d'avoir le même problème. 4 déclarations dans SSMS au lieu d'utiliser l'interface graphique et c'était très rapide.

  • Créer une nouvelle colonne

    alter table users add newusernum int;

  • Copier les valeurs sur

    update users set newusernum=usernum;

  • Abandonnez l'ancienne colonne

    alter table users drop column usernum;

  • Renommez la nouvelle colonne avec le nom de l'ancienne colonne.

    EXEC sp_RENAME 'users.newusernum' , 'usernum', 'COLUMN';

13voto

bluedot Points 135

Le script suivant supprime le champ Identité pour une colonne nommée 'Id'.

J'espère que cela vous aidera.

BEGIN TRAN
BEGIN TRY
    EXEC sp_rename '[SomeTable].[Id]', 'OldId';

    ALTER TABLE [SomeTable] ADD Id int NULL

    EXEC ('UPDATE [SomeTable] SET Id = OldId')

    ALTER TABLE [SomeTable] NOCHECK CONSTRAINT ALL

    ALTER TABLE [SomeTable] DROP CONSTRAINT [PK_constraintName];
    ALTER TABLE [SomeTable] DROP COLUMN OldId
    ALTER TABLE [SomeTable] ALTER COLUMN [Id] INTEGER NOT NULL
    ALTER TABLE [SomeTable] ADD CONSTRAINT PK_JobInfo PRIMARY KEY (Id)

    ALTER TABLE [SomeTable] CHECK CONSTRAINT ALL

    COMMIT TRAN
END TRY
BEGIN CATCH
    ROLLBACK TRAN   
    SELECT ERROR_MESSAGE ()
END CATCH

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X