Ajout d'une identité à une colonne existante

445

J'ai besoin de changer la clé primaire d'une table en une colonne d'identité, et il y a déjà un certain nombre de lignes dans la table.

J'ai un script pour nettoyer les ID pour s'assurer qu'ils sont séquentiels à partir de 1, fonctionne bien sur ma base de données de test.

Quelle est la commande SQL pour modifier la colonne pour avoir une propriété d'identité?

Kirschstein
la source

Réponses:

482

Vous ne pouvez pas modifier les colonnes existantes pour l'identité.

Vous avez 2 options,

  1. Créer une nouvelle table avec identité et supprimer la table existante

  2. Créer une nouvelle colonne avec identité et supprimer la colonne existante

Approche 1. ( Nouveau tableau ) Ici, vous pouvez conserver les valeurs de données existantes dans la colonne d'identité nouvellement créée.

CREATE TABLE dbo.Tmp_Names
    (
      Id int NOT NULL
             IDENTITY(1, 1),
      Name varchar(50) NULL
    )
ON  [PRIMARY]
go

SET IDENTITY_INSERT dbo.Tmp_Names ON
go

IF EXISTS ( SELECT  *
            FROM    dbo.Names ) 
    INSERT  INTO dbo.Tmp_Names ( Id, Name )
            SELECT  Id,
                    Name
            FROM    dbo.Names TABLOCKX
go

SET IDENTITY_INSERT dbo.Tmp_Names OFF
go

DROP TABLE dbo.Names
go

Exec sp_rename 'Tmp_Names', 'Names'

Approche 2 ( nouvelle colonne ) Vous ne pouvez pas conserver les valeurs de données existantes dans la colonne d'identité nouvellement créée, la colonne d'identité contiendra la séquence de nombres.

Alter Table Names
Add Id_new Int Identity(1, 1)
Go

Alter Table Names Drop Column ID
Go

Exec sp_rename 'Names.Id_new', 'ID', 'Column'

Consultez le message suivant du forum Microsoft SQL Server pour plus de détails:

Comment modifier la colonne en identité (1,1)

John Sansom
la source
49
Si les données de la table sont petites, cette option fonctionne parfaitement. Si la table est grande, il y a une autre option que je préfère: utilisez ALTER TABLE ... SWITCH pour remplacer le schéma de la table par une autre version avec une colonne IDENTITY mais sinon un schéma identique. L'avantage de l'approche ALTER TABLE .... SWITCH est qu'elle se termine rapidement (moins de 5 secondes pour une table à un milliard de lignes) car aucune donnée de table n'a besoin d'être copiée ou modifiée. Il y a cependant des mises en garde et des limites. Voir ma réponse ci-dessous pour plus de détails.
Justin Grant
7
@Justin Grat: Une alternative très intéressante et que je n'avais pas envisagée! La raison pour laquelle cela fonctionne est parce que IDENTITY est une propriété de colonne et non un type de données, donc la méthode SWITCH valide les schémas entre les deux tables (ancienne et nouvelle) comme étant identifiables indépendamment de la différence IDENTITY. Merci d'avoir partagé!
John Sansom
Si vous n'avez pas beaucoup de données, la "création de la table" peut être réalisée en générant un script à partir de SSMS. Cliquez avec le bouton droit sur la table> Scrip Table as> Create TABLE to> (nouvel éditeur de requête?). Ensuite, déposez-le et à l'intérieur de ce script, vous pouvez ajouter la IDENTITY(1, 1)partie avec la colonne de clé primaire
goamn
On peut également utiliser SSMS pour appliquer cela. Allez dans Outils> Options> Concepteurs> Décochez "Empêcher l'enregistrement des modifications qui nécessitent une recréation de table". BTW ce n'est pas recommandé pour les tables assez grandes.
Zafar
Dans PostgreSQL, vous pouvez ajouter une identité à une colonne entière existante avec la commande: alter table {nom_table} alter colonne {nom_colonne} add généré toujours comme identité (redémarrer avec {numéro});
Andrew Mackie
209

Dans SQL 2005 et versions ultérieures, il existe une astuce pour résoudre ce problème sans modifier les pages de données de la table. Ceci est important pour les grands tableaux où toucher chaque page de données peut prendre des minutes ou des heures. L'astuce fonctionne également même si la colonne d'identité est une clé primaire, fait partie d'un index clusterisé ou non clusterisé, ou d'autres pièges qui peuvent déclencher la solution la plus simple "ajouter / supprimer / renommer la colonne".

Voici l'astuce: vous pouvez utiliser l'instruction ALTER TABLE ... SWITCH de SQL Server pour modifier le schéma d'une table sans modifier les données, ce qui signifie que vous pouvez remplacer une table par une IDENTITY par un schéma de table identique, mais sans colonne IDENTITY. La même astuce fonctionne pour ajouter IDENTITY à une colonne existante.

Normalement, ALTER TABLE ... SWITCH est utilisé pour remplacer efficacement une partition complète dans une table partitionnée par une nouvelle partition vide. Mais il peut également être utilisé dans des tables non partitionnées.

J'ai utilisé cette astuce pour convertir, en moins de 5 secondes, une colonne d'une table de 2,5 milliards de lignes d'IDENTITY en non-IDENTITY (afin d'exécuter une requête de plusieurs heures dont le plan de requête fonctionnait mieux pour les non-IDENTITY colonnes), puis restauré le paramètre IDENTITY, à nouveau en moins de 5 secondes.

Voici un exemple de code de son fonctionnement.

 CREATE TABLE Test
 (
   id int identity(1,1),
   somecolumn varchar(10)
 );

 INSERT INTO Test VALUES ('Hello');
 INSERT INTO Test VALUES ('World');

 -- copy the table. use same schema, but no identity
 CREATE TABLE Test2
 (
   id int NOT NULL,
   somecolumn varchar(10)
 );

 ALTER TABLE Test SWITCH TO Test2;

 -- drop the original (now empty) table
 DROP TABLE Test;

 -- rename new table to old table's name
 EXEC sp_rename 'Test2','Test';

 -- update the identity seed
 DBCC CHECKIDENT('Test');

 -- see same records
 SELECT * FROM Test; 

Cela est évidemment plus complexe que les solutions des autres réponses, mais si votre table est grande, cela peut vous sauver la vie. Il y a quelques mises en garde:

  • Pour autant que je sache, l'identité est la seule chose que vous pouvez changer sur les colonnes de votre table avec cette méthode. L'ajout / la suppression de colonnes, la modification de la nullité, etc. n'est pas autorisé.
  • Vous devrez supprimer les clés foriegn avant d'effectuer le changement et les restaurer après.
  • Idem pour les fonctions, vues, etc. AVEC SCHEMABINDING.
  • les index des nouvelles tables doivent correspondre exactement (mêmes colonnes, même ordre, etc.)
  • Les anciennes et les nouvelles tables doivent se trouver dans le même groupe de fichiers.
  • Fonctionne uniquement sur SQL Server 2005 ou version ultérieure
  • Je pensais auparavant que cette astuce ne fonctionne que sur les éditions Enterprise ou Developer de SQL Server (car les partitions ne sont prises en charge que dans les versions Enterprise et Developer), mais Mason G. Zhwiti dans son commentaire ci-dessous dit qu'il fonctionne également dans SQL Standard Edition. Je suppose que cela signifie que la restriction à Enterprise ou Developer ne s'applique pas à ALTER TABLE ... SWITCH.

Il y a un bon article sur TechNet détaillant les exigences ci-dessus.

MISE À JOUR - Eric Wu avait un commentaire ci-dessous qui ajoute des informations importantes sur cette solution. Copiez-le ici pour vous assurer qu'il reçoit plus d'attention:

Il y a une autre mise en garde ici qui mérite d'être mentionnée. Bien que la nouvelle table reçoive avec plaisir les données de l'ancienne table et que toutes les nouvelles lignes soient insérées selon un modèle d'identité, elles commenceront à 1 et risquent de se casser si ladite colonne est une clé primaire. Pensez à courir DBCC CHECKIDENT('<newTableName>')immédiatement après le changement. Voir msdn.microsoft.com/en-us/library/ms176057.aspx pour plus d'informations.

Si la table est activement étendue avec de nouvelles lignes (ce qui signifie que vous n'avez pas beaucoup ou pas de temps d'arrêt entre l'ajout d'IDENTITY et l'ajout de nouvelles lignes, alors au lieu de DBCC CHECKIDENTvous voudrez définir manuellement la valeur de départ de l'identité dans le nouveau schéma de table pour être plus grand que le plus grand ID existant dans le tableau, par exemple IDENTITY (2435457, 1). Vous pourriez être en mesure d'inclure à la fois le ALTER TABLE...SWITCHet le DBCC CHECKIDENTdans une transaction (ou pas - je n'ai pas testé cela), mais il semble que la définition manuelle de la valeur de départ sera plus facile et plus sûre.

De toute évidence, si aucune nouvelle ligne n'est ajoutée à la table (ou si elles ne sont ajoutées qu'occasionnellement, comme un processus ETL quotidien), cette condition de concurrence critique ne se produira pas DBCC CHECKIDENT.

Justin Grant
la source
5
Si ma mémoire est correcte, j'ai eu l'idée de cet article: sqlservercentral.com/articles/T-SQL/61979
Justin Grant
2
Pour info, cela semble également fonctionner sur la version Standard de SQL 2008 R2. Peut-être qu'ils ont activé cette fonctionnalité tout comme ils ont désormais activé la possibilité d'activer la compression de sauvegarde.
Mason G. Zhwiti
3
@jbatista - la question du PO indiquait qu'il avait déjà une clé primaire sur la table et pouvait déjà garantir les bonnes valeurs, mais il voulait simplement la changer pour qu'elle soit une colonne IDENTITY. Ma réponse ci-dessus se concentre sur ce cas d'utilisation étroit: comment ajouter l'IDENTITÉ à une colonne sans réellement modifier les données. L'approche que je documente ci-dessus est un énorme gain de temps pour les grandes tables. Si vous devez modifier des données, vous devrez utiliser d'autres solutions.
Justin Grant du
3
Il y a une autre mise en garde ici qui mérite d'être mentionnée. Bien que la nouvelle table reçoive avec plaisir les données de l'ancienne table, et toutes les nouvelles lignes seront insérées selon un modèle d'identité, elles commenceront à 1 et risquent de se casser si ladite colonne est une clé primaire. Pensez à courir DBCC CHECKIDENT('<newTableName>')immédiatement après le changement. Voir msdn.microsoft.com/en-us/library/ms176057.aspx pour plus d'informations.
Eric Wu
3
C'est une excellente réponse! Notez également que la nullité des colonnes doit être la même. Donc, si vous devez modifier la nullité d'une colonne, vous devrez le faire à une étape ultérieure. Il en va de même pour les contraintes PK. Je modifie également la valeur d'identité dans la création de la table pour qu'elle corresponde au maximum actuel: IDENTITE (maxID + 1, 1)
Philippe
71

Vous ne pouvez pas modifier une colonne pour être une colonne IDENTITY. Ce que vous devez faire est de créer une nouvelle colonne qui est définie comme une IDENTITÉ dès le départ, puis de supprimer l'ancienne colonne et de renommer la nouvelle en l'ancien nom.

ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'

Marc

marc_s
la source
Soit le paramètre \ @objname est ambigu, soit le \ @objtype (COLUMN) est incorrect.
Jenny O'Reilly
1
@ JennyO'Reilly: mettez cela dans une question distincte et montrez-nous la commande complète que vous utilisez!
marc_s
2
C'était la procédure sp_rename qui échouait. J'ai trouvé une solution sur stackoverflow en recherchant le texte d'erreur. Il semble que ce soit une règle de syntaxe stricte avec des crochets, bien que ma table n'ait aucun caractère spécial dans son nom.
Jenny O'Reilly
1
ou cela pourrait être comme: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' et 'ALTER TABLE (yourTable) ADD OldColumnName INT IDENTITY (1,1)', pourquoi renommer: p
RK Sharma
Marc, j'ai essayé cette commande exacte sur une énorme table (~ 300 mln de lignes), mais j'ai arrêté le processus après ~ 10 min
Naomi
14

Il existe une solution intéressante décrite ici: SQL SERVER - Ajouter ou supprimer une propriété d'identité sur la colonne

En bref, modifiez manuellement votre table dans SQL Manager, changez l'identité, NE PAS ENREGISTRER les modifications, affichez simplement le script qui sera créé pour les modifications, copiez-le et utilisez-le plus tard.

C'est un gain de temps énorme, car il (le script) contient toutes les clés étrangères, les index, etc. liés à la table que vous modifiez. L'écriture manuelle ... Dieu ne plaise.

greenoldman
la source
c'est la solution que j'ai utilisée - SSMS génère le T-SQL pour effectuer le changement ... il le fait en créant une nouvelle table temporaire de la même conception de schéma, puis en copiant toutes les lignes, en supprimant l'orig et en renommant . peut prendre un peu de temps pour fonctionner complètement mais cela a parfaitement fonctionné.
mdelvecchio
Je ne pense pas que Pinal Dave dise en fait que vous devez exécuter le script que vous générez, c'est juste pour montrer ce que faire le changement via l'interface utilisateur fait pour vous ...
Zack
Cette fonctionnalité de script dans SSMS (sur la modification de la définition d'une table) est en fait la seule fonctionnalité correcte lors de la documentation d'une table partitionnée. L'emplacement le plus approprié 'tâche' -> 'table de script' oublie toujours de scripter la fonction de partitionnement!
Martijn van der Jagt
1
Peut être utile à quelqu'un. Pour obtenir le script de modification après les modifications. Cliquez avec le bouton droit sur la table en mode conception sur SSMS et sélectionnez l'option "Générer le script de changement" et enregistrez le script dans le lecteur local
Vijai
11

Pensez à utiliser SEQUENCE au lieu d'IDENTITY .

Dans SQL Server 2014 (je ne connais pas les versions inférieures), vous pouvez le faire simplement, en utilisant la séquence.

CREATE SEQUENCE  sequence_name START WITH here_higher_number_than_max_existed_value_in_column INCREMENT BY 1;

ALTER TABLE table_name ADD CONSTRAINT constraint_name DEFAULT NEXT VALUE FOR sequence_name FOR column_name

À partir d'ici: séquence comme valeur par défaut pour une colonne

Oto Shavadze
la source
6

Explication simple

Renommez la colonne existante à l'aide de sp_RENAME

EXEC sp_RENAME 'Table_Name.Existing_ColumnName', 'New_ColumnName', 'COLUMN'

Exemple pour renommer:

La colonne existante UserID est renommée OldUserID

EXEC sp_RENAME 'AdminUsers.UserID' , 'OldUserID', 'COLUMN'

Ajoutez ensuite une nouvelle colonne en utilisant alter query pour définir comme clé primaire et valeur d'identité

ALTER TABLE TableName ADD Old_ColumnName INT NOT NULL PRIMARY KEY IDENTITY(1,1)

Exemple pour définir la clé primaire

Le nouveau nom de colonne créé est UserID

ALTER TABLE Users ADD UserID INT NOT NULL PRIMARY KEY IDENTITY(1,1)

puis supprimez la colonne renommée

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Exemple pour la colonne renommée Drop

ALTER TABLE Users DROP COLUMN OldUserID

Nous avons maintenant ajouté une clé primaire et une identité à la colonne existante de la table.

Sathish Chelladurai
la source
5

Je suis un développeur java qui a fait partie d'une équipe sans DBA et où, en tant que développeur, je ne peux pas obtenir de droits DBA. J'ai été chargé de déplacer un schéma entier entre deux bases de données, donc sans avoir un DBA, je devais le faire et le faire en exécutant des scripts, ne pouvant pas utiliser l'interface graphique dans SQL Server 2008 car je n'avais pas de privilèges d'administrateur.

Tout a été déplacé sans problème, cependant, lors de l'exécution d'une procédure stockée sur la nouvelle table schema.table, j'ai trouvé que j'avais perdu le champ d'identité dans une table. J'ai revérifié le script qui a créé la table et il était là, cependant, SQL Server ne l'a pas obtenu lorsque j'ai exécuté le script. Un DBA m'a dit plus tard qu'il avait déjà vu ce même problème auparavant.

En tout état de cause, pour SQL Server 2008, ce sont les étapes que j'ai prises pour résoudre ce problème et cela a fonctionné, donc je le poste ici dans l'espoir que cela sera utile à quelqu'un. C'est ce que j'ai fait car j'avais des dépendances FK sur une autre table qui ont rendu cela plus difficile:

J'ai utilisé cette requête pour vérifier que l'identité était effectivement manquante et pour afficher les dépendances sur la table.

1.) Trouvez des statistiques sur un tableau:

exec sp_help 'dbo.table_name_old';

2.) Créez une nouvelle table identique en double, sauf ajoutez un champ d'identité sur le champ PK où il se trouvait auparavant.

3.) Désactivez l'identité pour déplacer les données.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Transférez les données.

INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT 
field1, field2, etc...
FROM 
dbo.table_name_old;

5.) Vérifiez que les données sont là.

SELECT * FROM dbo.table_name_new

6.) Réactivez l'identité.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) C'est le meilleur script que j'ai trouvé pour obtenir toutes les relations FK pour vérifier quelle (s) table (s) les références de table d'origine en tant que dépendances et j'en ai rencontré beaucoup, c'est donc un gardien!

SELECT f.name AS ForeignKey,
   OBJECT_NAME(f.parent_object_id) AS TableName,
   COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
   OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
   COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
   ON f.OBJECT_ID = fc.constraint_object_id
   ORDER BY ReferenceTableName;

8.) Assurez-vous que vous disposez de tous les scripts PK et FK pour toutes les tables impliquées, avant cette étape suivante.

9.) Vous pouvez cliquer avec le bouton droit sur chaque clé et l'écrire à l'aide de SQL Server 2008

10.) Supprimez les FK de la ou des tables de dépendances en utilisant cette syntaxe:

ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]

11.) Déposez la table d'origine:

DROP TABLE dbo.table_name_old;

13.) Ces étapes suivantes s'appuient sur les scripts que vous avez créés dans SQL Server 2008 à l'étape 9.

--Ajouter le PK à la nouvelle table.

--Ajouter le FK à la nouvelle table.

--Ajouter le dos du FK à la table des dépendances.

14.) Vérifiez que tout est correct et complet. J'ai utilisé l'interface graphique pour regarder les tableaux.

15.) Renommez la nouvelle table en son nom d'origine.

exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';

Enfin, tout a fonctionné!

James Drinkard
la source
4

vous ne pouvez pas le faire comme ça, vous devez ajouter une autre colonne, supprimer la colonne d'origine et renommer la nouvelle colonne ou créer une nouvelle table, copier les données et supprimer l'ancienne table, puis renommer la nouvelle table en l'ancienne table

si vous utilisez SSMS et définissez la propriété d'identité sur ON dans le concepteur, voici ce que fait SQL Server en arrière-plan. Donc, si vous avez une table nommée [utilisateur], c'est ce qui se passe si vous définissez UserID et identité

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION

GO

GO
CREATE TABLE dbo.Tmp_User
    (
    UserID int NOT NULL IDENTITY (1, 1),
    LastName varchar(50) NOT NULL,
    FirstName varchar(50) NOT NULL,
    MiddleInitial char(1) NULL

    )  ON [PRIMARY]
GO

SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
 EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
    SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO

GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
    PK_User PRIMARY KEY CLUSTERED 
    (
    UserID
    ) ON [PRIMARY]

GO
COMMIT

Cela dit, il existe un moyen de pirater la table système pour y parvenir en définissant la valeur au niveau du bit, mais cela n'est pas pris en charge et je ne le ferais pas

SQLMenace
la source
4

Comme je l' ai compris dans les cas normaux , nous créons une table avec clé primaire qui est d' avoir la propriété Identity
Ainsi Renommer ou Supprimer une colonne qui est associée à la clé primaire contrainte ne sera pas possible parce que les règles de contrainte valident la structure de la colonne.
Pour y parvenir, nous devons traiter certaines étapes de la manière suivante:
Supposons que TableName = 'Employee' et ColumnName = 'EmployeeId'

1. Ajoutez une nouvelle colonne 'EmployeeId_new' dans la table 'Employee'
ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY ( 1,1)

  1. Maintenant, supprimez la colonne 'EmployeeId' de la table 'Employee'
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Cela générera une erreur car les règles de contrainte de clé primaire sont applicables et valident la structure des colonnes.
    * ### ' Msg 5074, niveau 16, état 1, ligne 1 L'objet [PK_dbo.Employee] dépend de colmn [EmployeeId].' ###

  3. Nous devons donc d'abord supprimer la contrainte de clé primaire de la table 'Employé', puis nous pouvons supprimer la colonne
    ALTER TABLE Contrainte DROP des employés [PK_dbo.Employee]

  4. Maintenant, nous pouvons supprimer la colonne 'EmployeeId' de la table 'Employee' comme cela a été fait à l'étape précédente où nous avons eu une erreur
    ALTER TABLE Employee DROP COLUMN EmployeeId

  5. Maintenant, la colonne 'EmployeeId' a été supprimée du tableau. Nous allons donc renommer la nouvelle colonne 'EmployeeId_new' nouvellement ajoutée avec 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN'

  6. Pour réorganiser la table sous la même forme qu'elle l'était, nous devons ajouter la contrainte de clé primaire pour la colonne 'EmployeeId'
    ALTER TABLE Clé primaire de contrainte d'ajout d'employé [PK_dbo.Employee] (EmployeeId)

8. Maintenant, la table «Employee» avec «EmployeeId» est modifiée pour les règles d'identité avec la contrainte de clé primaire existante

Nagendra Upwanshi
la source
3

De par sa conception, il n'existe aucun moyen simple d'activer ou de désactiver la fonctionnalité d'identité pour une colonne existante. La seule façon propre de le faire est de créer une nouvelle colonne et d'en faire une colonne d'identité ou de créer une nouvelle table et de migrer vos données.

Si nous utilisons SQL Server Management Studio pour supprimer la valeur d'identité de la colonne "id", une nouvelle table temporaire est créée, les données sont déplacées vers la table temporaire, l'ancienne table est supprimée et la nouvelle table est renommée.

Utilisez Management Studio pour effectuer la modification, puis cliquez avec le bouton droit dans le concepteur et sélectionnez "Générer le script de modification".

Vous verrez que c'est ce que fait SQL Server en arrière-plan.

Raj
la source
2

Il n'y en a pas, malheureusement; la propriété IDENTITY appartient à la table plutôt qu'à la colonne.

Le moyen le plus simple est de le faire dans l'interface graphique, mais si ce n'est pas une option, vous pouvez faire le long chemin pour copier les données, supprimer la colonne, la rajouter avec l'identité et remettre les données.

Voir ici pour un compte coup par coup.

Jeremy Smyth
la source
2

Cliquez avec le bouton droit sur le nom de la table dans l'Explorateur d'objets. Vous obtiendrez quelques options. Cliquez sur «Design». Un nouvel onglet sera ouvert pour ce tableau. Vous pouvez ajouter une contrainte d'identité ici dans «Propriétés de la colonne».

vamsi_874
la source
2

Pour modifier les propriétés d'identité d'une colonne:

  • Dans l'Explorateur de serveurs, cliquez avec le bouton droit sur la table avec les propriétés d'identité que vous souhaitez modifier et cliquez sur Ouvrir la définition de table. La table s'ouvre dans Table Designer.
  • Décochez la case Autoriser les valeurs nulles pour la colonne que vous souhaitez modifier.
  • Dans l'onglet Propriétés de la colonne, développez la propriété Spécification d'identité.
  • Cliquez sur la cellule de la grille pour la propriété enfant Is Identity et choisissez Oui dans la liste déroulante.
  • Tapez une valeur dans la cellule Graine d'identité. Cette valeur sera affectée à la première ligne du tableau. La valeur 1 sera attribuée par défaut.

C'est ça, et ça a marché pour moi

Ken.Fukizi
la source
2

Si vous utilisez Visual Studio 2017+

  1. Dans l'Explorateur d'objets serveur, cliquez avec le bouton droit sur votre table et sélectionnez "Afficher le code"
  2. Ajoutez le modificateur "IDENTITY" à votre colonne
  3. Mise à jour

Cela fera tout pour vous.

jdisla
la source
Oui! Merci d'avoir suggéré cela! Je n'ai pas de version de SSMS sur ma boîte Windows 7 qui me permet d'apporter des modifications de conception aux tables de mon serveur de production car c'est 2017, mon SSMS est 2014 et 2017 SSMS a besoin de Windows 10. Vous avez fait ma journée. Entré dans VS 2017> Explorateur de serveurs> établi une nouvelle connexion à la production SQL Server> cliqué avec le bouton droit sur la table> "Définition de la table ouverte"> Wala!
JustJohn
En fait, j'ai trouvé que vous pouvez cliquer avec le bouton droit sur le champ et sélectionner Propriétés et créer l'identité là-bas en choisissant Oui ou Non
JustJohn
1

Si l'affiche d'origine voulait réellement définir une colonne existante comme une PRIMARY KEYpour la table et n'avait pas besoin que la colonne soit une IDENTITYcolonne (deux choses différentes), cela peut être fait via t-SQL avec:

ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])

Notez la parenthèse autour du nom de la colonne après l' PRIMARY KEYoption.

Bien que ce message soit ancien et que je fasse une supposition sur les besoins des demandeurs, je pensais que ces informations supplémentaires pourraient être utiles aux utilisateurs rencontrant ce fil car je pense que la conversation pourrait faire croire qu'une colonne existante ne peut pas être définie comme un clé primaire sans l'ajouter en tant que nouvelle colonne, ce qui serait incorrect.

A. Omalley
la source
1

Selon mon état actuel, je suis cette approche. Je veux donner une identité à une table primaire après l'insertion de données via un script.

Comme je veux ajouter une identité, cela commence toujours de 1 à la fin du nombre d'enregistrements que je veux.

--first drop column and add with identity
ALTER TABLE dbo.tblProductPriceList drop column ID 
ALTER TABLE dbo.tblProductPriceList add ID INT IDENTITY(1,1)

--then add primary key to that column (exist option you can ignore)
IF  NOT EXISTS (SELECT * FROM sys.key_constraints  WHERE object_id = OBJECT_ID(N'[dbo].[PK_tblProductPriceList]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblProductPriceList]'))
    ALTER TABLE [tblProductPriceList] ADD PRIMARY KEY (id)
GO

Cela créera la même colonne de clé primaire avec l'identité

J'ai utilisé ces liens: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Ajouter une clé primaire à une table existante

Ajay2707
la source
0

Je ne pense pas que vous puissiez modifier une colonne existante pour être une colonne d'identité à l'aide de tsql. Cependant, vous pouvez le faire via la vue de conception Enterprise Manager.

Vous pouvez également créer une nouvelle ligne comme colonne d'identité, supprimer l'ancienne colonne, puis renommer votre nouvelle colonne.

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED
William Edmondson
la source
2
gardez à l'esprit que si vous le faites via SSMS / Enterprise Manager - vous allez créer une nouvelle table, copier des données, supprimer l'ancienne table et renommer la nouvelle. Cela peut être assez cher lorsque vous avez de grandes tables ...
Scott Ivey
0

Fondamentalement, il y a quatre étapes logiques.

  1. Créez une nouvelle colonne d'identité. Activez Insérer une identité pour cette nouvelle colonne.

  2. Insérez les données de la colonne source (la colonne que vous souhaitez convertir en identité) dans cette nouvelle colonne.

  3. Désactivez l'option Insérer une identité pour la nouvelle colonne.

  4. Déposez votre colonne source et renommez la nouvelle colonne au nom de la colonne source.

Il peut y avoir quelques complexités plus comme travailler sur plusieurs serveurs, etc.

Veuillez consulter l'article suivant pour les étapes (à l'aide de ssms et T-sql). Ces étapes sont destinées aux débutants avec moins d'adhérence sur T-SQL.

http://social.technet.microsoft.com/wiki/contents/articles/23816.how-to-convert-int-column-to-identity-in-the-ms-sql-server.aspx

Shivalik Chakravarty
la source
0

génère un script pour toutes les tables avec clé primaire = bigint qui n'ont pas d'identité définie; cela renverra une liste de scripts générés avec chaque table;

SET NOCOUNT ON;

declare @sql table(s varchar(max), id int identity)

DECLARE @table_name nvarchar(max),
        @table_schema nvarchar(max);

DECLARE vendor_cursor CURSOR FOR 
SELECT
  t.name, s.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
  ON s.[schema_id] = t.[schema_id]
WHERE EXISTS (
    SELECT
    [c].[name]
    from sys.columns [c]
    join sys.types [y] on [y].system_type_id = [c].system_type_id
    where [c].[object_id] = [t].[object_id] and [y].name = 'bigint' and [c].[column_id] = 1
) and NOT EXISTS 
(
  SELECT 1 FROM sys.identity_columns
    WHERE [object_id] = t.[object_id]
) and exists (
    select 1 from sys.indexes as [i] 
    inner join sys.index_columns as [ic]  ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
    where object_name([ic].[object_id]) = [t].[name]
)
OPEN vendor_cursor

FETCH NEXT FROM vendor_cursor 
INTO @table_name, @table_schema

WHILE @@FETCH_STATUS = 0
BEGIN

DELETE FROM @sql

declare @pkname varchar(100),
    @pkcol nvarchar(100)

SELECT  top 1
        @pkname = i.name,
        @pkcol = COL_NAME(ic.OBJECT_ID,ic.column_id)
FROM    sys.indexes AS [i]
INNER JOIN sys.index_columns AS [ic] ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE   i.is_primary_key = 1 and OBJECT_NAME(ic.OBJECT_ID) = @table_name

declare @q nvarchar(max) = 'SELECT  '+@pkcol+' FROM ['+@table_schema+'].['+@table_name+'] ORDER BY '+@pkcol+' DESC'

DECLARE @ident_seed nvarchar(max) -- Change this to the datatype that you are after
SET @q = REPLACE(@q, 'SELECT', 'SELECT TOP 1 @output = ')
EXEC sp_executeSql @q, N'@output bigint OUTPUT', @ident_seed OUTPUT

insert into  @sql(s) values ('BEGIN TRANSACTION')
insert into  @sql(s) values ('BEGIN TRY')

-- create statement
insert into  @sql(s) values ('create table ['+@table_schema+'].[' + @table_name + '_Temp] (')

-- column list
insert into @sql(s) 
select 
    '  ['+[c].[name]+'] ' +
    y.name + 

    (case when [y].[name] like '%varchar' then
    coalesce('('+(case when ([c].[max_length] < 0 or [c].[max_length] >= 1024) then 'max' else cast([c].max_length as varchar) end)+')','')
    else '' end)

     + ' ' +
    case when [c].name = @pkcol then 'IDENTITY(' +COALESCE(@ident_seed, '1')+',1)' else '' end + ' ' +
    ( case when c.is_nullable = 0 then 'NOT ' else '' end ) + 'NULL ' + 
    coalesce('DEFAULT ('+(
        REPLACE(
            REPLACE(
                LTrim(
                    RTrim(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        LTrim(
                                            RTrim(
                                                REPLACE(
                                                    REPLACE(
                                                        object_definition([c].default_object_id)
                                                    ,' ','~')
                                                ,')',' ')
                                            )
                                        )
                                    ,' ','*')
                                ,'~',' ')
                            ,' ','~')
                        ,'(',' ')
                    )
                )
            ,' ','*')
        ,'~',' ')
    ) +
    case when object_definition([c].default_object_id) like '%get%date%' then '()' else '' end
    +
    ')','') + ','
 from sys.columns c
 JOIN sys.types y ON y.system_type_id = c.system_type_id
  where OBJECT_NAME(c.[object_id]) = @table_name and [y].name != 'sysname'
 order by [c].column_id


 update @sql set s=left(s,len(s)-1) where id=@@identity

-- closing bracket
insert into @sql(s) values( ')' )

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] ON')

declare @cols nvarchar(max)
SELECT @cols = STUFF(
    (
        select ',['+c.name+']'
        from sys.columns c
        JOIN sys.types y ON y.system_type_id = c.system_type_id
        where c.[object_id] = OBJECT_ID(@table_name)
        and [y].name != 'sysname'
        and [y].name != 'timestamp'
        order by [c].column_id
        FOR XML PATH ('')
     )
    , 1, 1, '')

insert into @sql(s) values( 'IF EXISTS(SELECT * FROM ['+@table_schema+'].['+@table_name+'])')
insert into @sql(s) values( 'EXEC(''INSERT INTO ['+@table_schema+'].['+@table_name+'_Temp] ('+@cols+')')
insert into @sql(s) values( 'SELECT '+@cols+' FROM ['+@table_schema+'].['+@table_name+']'')')

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] OFF')


insert into @sql(s) values( 'DROP TABLE ['+@table_schema+'].['+@table_name+']')

insert into @sql(s) values( 'EXECUTE sp_rename N''['+@table_schema+'].['+@table_name+'_Temp]'', N'''+@table_name+''', ''OBJECT''')

if ( @pkname is not null ) begin
    insert into @sql(s) values('ALTER TABLE ['+@table_schema+'].['+@table_name+'] ADD CONSTRAINT ['+@pkname+'] PRIMARY KEY CLUSTERED (')
    insert into @sql(s)
        select '  ['+COLUMN_NAME+'] ASC,' from information_schema.key_column_usage
        where constraint_name = @pkname
        GROUP BY COLUMN_NAME, ordinal_position
        order by ordinal_position

    -- remove trailing comma
    update @sql set s=left(s,len(s)-1) where id=@@identity
    insert into @sql(s) values ('  )')
end

insert into  @sql(s) values ('--Run your Statements')
insert into  @sql(s) values ('COMMIT TRANSACTION')
insert into  @sql(s) values ('END TRY')
insert into  @sql(s) values ('BEGIN CATCH')
insert into  @sql(s) values ('        ROLLBACK TRANSACTION')
insert into  @sql(s) values ('        DECLARE @Msg NVARCHAR(MAX)  ')
insert into  @sql(s) values ('        SELECT @Msg=ERROR_MESSAGE() ')
insert into  @sql(s) values ('        RAISERROR(''Error Occured: %s'', 20, 101,@msg) WITH LOG')
insert into  @sql(s) values ('END CATCH')

declare @fqry nvarchar(max)

-- result!
SELECT @fqry = (select char(10) + s from @sql order by id FOR XML PATH (''))


SELECT @table_name as [Table_Name], @fqry as [Generated_Query]
PRINT 'Table: '+@table_name
EXEC sp_executeSql @fqry

    FETCH NEXT FROM vendor_cursor 
    INTO @table_name, @table_schema
END 
CLOSE vendor_cursor;
DEALLOCATE vendor_cursor;
Kyle Gibbar
la source