web-dev-qa-db-fra.com

SQL Server, Comment définir l'incrémentation automatique après la création d'une table sans perte de données?

J'ai une table table1 dans SQL Server 2008 et elle contient des enregistrements. 

Je veux que la colonne de clé primaire table1_Sno soit une colonne à incrémentation automatique. Cela peut-il être fait sans transfert de données ni clonage de table?

Je sais que je peux utiliser ALTER TABLE pour ajouter une colonne à incrémentation automatique, mais puis-je simplement ajouter l'option AUTO_INCREMENT à une colonne existante qui est la clé primaire?

47
Shankar

La modification de la propriété IDENTITY est en réalité un changement de métadonnées uniquement. Mais pour mettre à jour les métadonnées directement, il faut démarrer l'instance en mode mono-utilisateur et déconner avec certaines colonnes de sys.syscolpars et n'est pas documenté/non pris en charge et ce n'est pas quelque chose que je recommanderais ou donnerais de plus amples détails.

Pour les personnes rencontrant cette réponse sur SQL Server 2012+, le moyen le plus simple d'obtenir ce résultat pour une colonne à incrémentation automatique serait de créer un objet SEQUENCE et de définir le next value for seq comme colonne par défaut.

Alternativement, ou pour les versions précédentes (à partir de 2005), la solution de contournement publiée sur cet élément de connexion montre une méthode complètement prise en charge, sans avoir besoin de la taille des opérations de données à l'aide de ALTER TABLE...SWITCH. Également blogué à propos de MSDN ici . Bien que le code permettant d'y parvenir ne soit pas très simple et qu'il existe des restrictions - par exemple, la table en cours de modification ne peut pas être la cible d'une contrainte de clé étrangère.

Exemple de code.

Configurez la table de test sans colonne identity.

CREATE TABLE dbo.tblFoo 
(
bar INT PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)


INSERT INTO dbo.tblFoo (bar)
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1, master..spt_values v2

Modifiez-le pour avoir une colonne identity (plus ou moins instantanée).

BEGIN TRY;
    BEGIN TRANSACTION;

    /*Using DBCC CHECKIDENT('dbo.tblFoo') is slow so use dynamic SQL to
      set the correct seed in the table definition instead*/
    DECLARE @TableScript nvarchar(max)
    SELECT @TableScript = 
    '
    CREATE TABLE dbo.Destination(
        bar INT IDENTITY(' + 
                     CAST(ISNULL(MAX(bar),0)+1 AS VARCHAR) + ',1)  PRIMARY KEY,
        filler CHAR(8000),
        filler2 CHAR(49)
        )

        ALTER TABLE dbo.tblFoo SWITCH TO dbo.Destination;
    '       
    FROM dbo.tblFoo
    WITH (TABLOCKX,HOLDLOCK)

    EXEC(@TableScript)


    DROP TABLE dbo.tblFoo;

    EXECUTE sp_rename N'dbo.Destination', N'tblFoo', 'OBJECT';


    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
    PRINT ERROR_MESSAGE();
END CATCH;

Testez le résultat.

INSERT INTO dbo.tblFoo (filler,filler2) 
OUTPUT inserted.*
VALUES ('foo','bar')

Donne

bar         filler    filler2
----------- --------- ---------
10001       foo       bar      

Nettoyer

DROP TABLE dbo.tblFoo
63
Martin Smith

SQL Server: Comment définir l'incrémentation automatique sur une table contenant des lignes:

Cette stratégie copie physiquement les lignes deux fois environ, ce qui peut prendre beaucoup plus de temps si la table que vous copiez est très grande. 

Vous pouvez sauvegarder vos données, supprimer et reconstruire la table avec l'incrémentation automatique et la clé primaire, puis recharger les données. 

Je vais vous guider avec un exemple:

Étape 1, créer une table foobar (sans clé primaire ni incrémentation automatique):

CREATE TABLE foobar(
    id int NOT NULL,
    name nchar(100) NOT NULL,
)

Étape 2, insérez quelques lignes

insert into foobar values(1, 'one');
insert into foobar values(2, 'two');
insert into foobar values(3, 'three');

Étape 3, copier les données foobar dans une table temporaire:

select * into temp_foobar from foobar

Étape 4, déposer la table foobar:

drop table foobar;

Étape 5, recréez votre table avec les propriétés de clé primaire et d'incrémentation automatique:

CREATE TABLE foobar(
    id int primary key IDENTITY(1, 1) NOT NULL,
    name nchar(100) NOT NULL,
)

Étape 6, insérez vos données de la table temporaire dans foobar

SET IDENTITY_INSERT temp_foobar ON
INSERT into foobar (id, name) select id, name from temp_foobar;

Étape 7, supprimez votre table temporaire et vérifiez si cela a fonctionné:

drop table temp_foobar;
select * from foobar;

Vous devriez l'obtenir, et lorsque vous inspectez la table foobar, la colonne id est incrémentée automatiquement de 1 et id est une clé primaire:

1    one
2    two
3    three
4
Eric Leschinski

Si vous souhaitez le faire via le concepteur, vous pouvez le faire en suivant les instructions ici "Enregistrer les modifications n'est pas autorisé" lors de la modification d'une colonne existante pour qu'elle soit Null -

3
Daveo

Oui, vous pouvez. Allez dans Outils> Designers> Table et Designers et décochez "Empêcher l'enregistrement des modifications empêchant la création de tables" .

2
Peter Pauletto

Si vous ne souhaitez pas ajouter de nouvelle colonne et que vous pouvez garantir que votre colonne int actuelle est unique, vous pouvez sélectionner toutes les données dans une table temporaire, supprimer la table et la recréer avec la colonne IDENTITY spécifiée. Ensuite, en utilisant SET IDENTITY INSERT ON, vous pouvez insérer toutes vos données de la table temporaire dans la nouvelle table.

2
Duncan Howe

Non, vous ne pouvez pas ajouter d’option d’incrémentation automatique à une colonne existante contenant des données. Je pense que l’option que vous avez mentionnée est la meilleure.

Regardez ici .

1
Homam

Le script ci-dessous peut être une bonne solution. Travaillé également dans des données volumineuses.

ALTER DATABASE WMlive SET RECUPERER SIMPLE AVEC NO_WAIT

ALTER TABLE WMBOMTABLE DROP CONSTRAINT PK_WMBomTable

ALTER TABLE WMBOMTABLE colonne de dépôt BOMID

ALTER TABLE WMBOMTABLE ADD BomID int IDENTITY (1, 1) NON NUL;

ALTER TABLE WMBOMTABLE AJOUTER UN CONTRAINT PK_WMBomTable PRIMARY KEY CLUSTERED (BomID);

ALTER DATABASE WMlive SET RÉCUPÉRATION PLEINE AVEC NO_WAIT

0
Jatin Dave