Comment mettre à jour la colonne d'identité dans SQL Server?


208

J'ai une base de données SQL Server et je veux changer la colonne d'identité car elle a commencé par un grand nombre 10010et elle est liée à une autre table, maintenant j'ai 200 enregistrements et je souhaite résoudre ce problème avant que les enregistrements n'augmentent.

Quelle est la meilleure façon de modifier ou de réinitialiser cette colonne?

Réponses:


281

Vous ne pouvez pas mettre à jour la colonne d'identité.

SQL Server ne permet pas de mettre à jour la colonne d'identité contrairement à ce que vous pouvez faire avec d'autres colonnes avec une instruction de mise à jour.

Bien qu'il existe des alternatives pour atteindre un type d'exigence similaire.

  • Lorsque la valeur de la colonne Identité doit être mise à jour pour les nouveaux enregistrements

Utilisez DBCC CHECKIDENT qui vérifie la valeur d'identité actuelle pour la table et si nécessaire, modifie la valeur d'identité.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Quand la valeur de la colonne Identité doit être mise à jour pour les enregistrements existants

Utilisez IDENTITY_INSERT qui permet d'insérer des valeurs explicites dans la colonne d'identité d'une table.

SET IDENTITY_INSERT YourTable {ON|OFF}

Exemple:

-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF

6
DBCC Réinitialisez le nouvel enregistrement suivant, mais ce que je veux maintenant changer les enregistrements existants.
Abdulsalam Elsharif

pouvez-vous donner un exemple s'il vous plaît?
Abdulsalam Elsharif

39
@sachin cela ne met pas à jour une IDENTITÉ existante que cela insère manuellement
Phill Greggan

3
@PhillGreggan oui, c'est la meilleure solution possible pour y parvenir. Vous ne pouvez pas mettre à jour la colonne Identité lorsque vous mettez à jour les colonnes normales.
Sachin le

19
Cette réponse acceptée ne répond pas à la question, à savoir comment mettre à jour une colonne d'identité (par exemple UPDATE YourTable SET IdentityCol = 13). SET IDENTITY_INSERT YourTable ONn'autorise que les INSERTs, pas les UPDATE.
Ian Boyd

62

Si votre question est correcte, vous voulez faire quelque chose comme

update table
set identity_column_name = some value

Permettez-moi de vous dire que ce n'est pas un processus facile et qu'il n'est pas conseillé de l'utiliser, car il peut y avoir des foreign keyassociés.

Mais voici les étapes pour le faire, veuillez prendre un back-uptableau

Étape 1 - Sélectionnez la vue de conception de la table

entrez la description de l'image ici

Étape 2 - Désactivez la colonne d'identité

entrez la description de l'image ici

Vous pouvez maintenant utiliser la updaterequête.

Maintenant, redopassez à l'étape 1 et à l'étape 2 et activez la colonne d'identité

Référence


1
J'ai une autre table liée à cette table, je ne peux pas faire ça
Abdulsalam Elsharif

4
D'où la déclaration qu'il n'est pas conseillé :)
Prahalad Gaggar

3
@AbdusalamElsherif Mais vous avez demandé comment changer la colonne d'identité.
paparazzo

@luv au moins vous avez répondu à la question qui a été posée
Phill Greggan

J'utilise cette procédure pour définir l'identifiant dans ma base de données de développement. Ce serait bien s'il y avait une commande qui me permette de le faire de toute façon, mais cela fonctionne.
Jeff Davis

59

Tu dois

set identity_insert YourTable ON

Supprimez ensuite votre ligne et réinsérez-la avec une identité différente.

Une fois que vous avez terminé l'insertion, n'oubliez pas de désactiver identity_insert

set identity_insert YourTable OFF

C'est tellement plus facile et plus sûr que de désactiver l'identité pour la colonne!
Protector one le

C'est plus sûr et facile pour un petit nombre d'enregistrements, mais ne répond pas correctement à la question. La désactivation de l'identité, bien que plus dangereuse et parfois impossible, vous permet de mettre à jour la colonne d'identité.
Matthew Hudson

18
--before running this make sure Foreign key constraints have been removed that reference the ID. 

--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT * 
INTO #tmpYourTable
FROM yourTable

--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO

1
Juste un conseil de performance si la table est très grande, au lieu de faire une suppression sur la table, faites un Tronquer la table yourTable. C'est instantané. Attention cependant, pas de retour en arrière avec tronquer car il n'est pas enregistré.
kuklei


5

copiez votre table dans une nouvelle table sans colonne d'identité.

    select columns into newtable from yourtable

ajouter une colonne d'identité à newtable avec une nouvelle graine et en faire une clé primaire

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

4
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName 
(
    TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
    TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)

SET IDENTITY_INSERT dbo.TableName OFF

Lorsque vous utilisez Identity_Insert, n'oubliez pas d'inclure les noms de colonne car sql ne vous permettra pas d'insérer sans les spécifier


3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = donne la table dont vous souhaitez réinitialiser la valeur

valeur = valeur initiale égale à zéro, pour commencer la colonne d'identité avec 1


2

Vous pouvez également utiliser SET IDENTITY INSERTpour vous permettre d'insérer des valeurs dans une colonne d'identité.

Exemple:

SET IDENTITY_INSERT dbo.Tool ON
GO

Et puis vous pouvez insérer dans une colonne d'identité les valeurs dont vous avez besoin.


1
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition

Cependant, le code ci-dessus ne fonctionne que s'il n'y a pas de relation clé primaire-étrangère


1

Solution complète pour les programmeurs C # utilisant le générateur de commandes

Tout d'abord, vous devez connaître ces faits:

  • Dans tous les cas, vous ne pouvez pas modifier une colonne d'identité, vous devez donc supprimer la ligne et la rajouter avec une nouvelle identité.
  • Vous ne pouvez pas supprimer la propriété d'identité de la colonne (vous devrez la supprimer dans la colonne)
  • Le générateur de commandes personnalisées de .net ignore toujours la colonne d'identité, vous ne pouvez donc pas l'utiliser à cette fin.

Donc, une fois que vous savez cela, ce que vous devez faire est. Programmez votre propre instruction SQL Insert ou programmez votre propre générateur de commandes d'insertion. Ou utilisez celui que je suis programmé pour vous. Étant donné un DataTable, génère le script SQL Insert:

public static string BuildInsertSQLText ( DataTable table )
{
    StringBuilder sql = new StringBuilder(1000,5000000);
    StringBuilder values = new StringBuilder ( "VALUES (" );
    bool bFirst = true;
    bool bIdentity = false;
    string identityType = null;

    foreach(DataRow myRow in table.Rows) 
    {
        sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );

        foreach ( DataColumn column in table.Columns )
        {
            if ( column.AutoIncrement )
            {
                bIdentity = true;

                switch ( column.DataType.Name )
                {
                    case "Int16":
                        identityType = "smallint";
                        break;
                    case "SByte":
                        identityType = "tinyint";
                        break;
                    case "Int64":
                        identityType = "bigint";
                        break;
                    case "Decimal":
                        identityType = "decimal";
                        break;
                    default:
                        identityType = "int";
                        break;
                }
            }
            else
            {
                if ( bFirst )
                    bFirst = false;
                else
                {
                    sql.Append ( ", " );
                    values.Append ( ", " );
                }
                sql.Append ("[");
                sql.Append ( column.ColumnName );
                sql.Append ("]");

                //values.Append (myRow[column.ColumnName].ToString() );

                if (myRow[column.ColumnName].ToString() == "True")
                    values.Append("1");
                else if (myRow[column.ColumnName].ToString() == "False")
                    values.Append("0");
                else if(myRow[column.ColumnName] == System.DBNull.Value)    
                    values.Append ("NULL");
                else if(column.DataType.ToString().Equals("System.String"))
                {
                    values.Append("'"+myRow[column.ColumnName].ToString()+"'");
                }
                else
                    values.Append (myRow[column.ColumnName].ToString());
                    //values.Append (column.DataType.ToString() );
            }
        }
        sql.Append ( ") " );
        sql.Append ( values.ToString () );
        sql.Append ( ")" );

        if ( bIdentity )
        {
            sql.Append ( "; SELECT CAST(scope_identity() AS " );
            sql.Append ( identityType );
            sql.Append ( ")" );
        }
        bFirst = true;
        sql.Append(";");
        values = new StringBuilder ( "VALUES (" );
    } //fin foreach
    return sql.ToString ();
}

0

J'ai résolu ce problème en utilisant d'abord DBCC, puis en utilisant insert. Par exemple si votre table est

Commencez par définir la nouvelle valeur d'ID actuelle sur la table comme NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

alors vous pouvez utiliser

    insert into MyTable (colA, ColB) select colA, colB from MyTable

Cela dupliquerait tous vos enregistrements, mais en utilisant une nouvelle valeur IDCol commençant par NEW_RESEED_VALUE. Vous pouvez ensuite supprimer les lignes en double de valeur d'ID supérieure une fois que vous avez supprimé / déplacé leurs références de clé étrangère, le cas échéant.


1
C'est une idée décente, mais la New_reseed_value est la graine actuelle, et le prochain nombre qui sera utilisé sera 1 de plus que cette valeur. Donc, si vous voulez que la prochaine ligne insérée soit l'identité 10, alors NEW_RESEED_VALUE doit être défini sur 9.
LarryBud

0

Vous pouvez créer une nouvelle table à l'aide du code suivant.

SELECT IDENTITY (int, 1, 1) AS id, column1, column2
INTO dbo.NewTable
FROM dbo.OldTable

Supprimez ensuite l'ancienne base de données et renommez la nouvelle base de données avec le nom de l'ancienne base de données. Remarque : cette colonne1 et colonne2 représentent toutes les colonnes de votre ancienne table que vous souhaitez conserver dans votre nouvelle table.


0

Si vous avez spécifiquement besoin de changer la valeur de la clé primaire en un nombre différent (ex 123 -> 1123). La propriété d'identité bloque la modification d'une valeur PK. Définir Identity_insert ne fonctionnera pas. Il n'est pas conseillé d'effectuer une insertion / suppression si vous avez des suppressions en cascade (sauf si vous désactivez la vérification de l'intégrité référentielle).

Ce script désactivera l'identité sur un PK:

***********************

sp_configure 'allow update', 1
go
reconfigure with override
go


update syscolumns set colstat = 0 --turn off bit 1 which indicates identity column
where id = object_id('table_name') and name = 'column_name'
go


exec sp_configure 'allow update', 0
go
reconfigure with override
go

***********************

Ensuite, vous pouvez définir les relations afin qu'elles mettent à jour les références de clé étrangère. Sinon, vous devez désactiver l'application des relations. Ce lien SO montre comment: Comment les contraintes de clé étrangère peuvent-elles être temporairement désactivées à l'aide de T-SQL?

Maintenant, vous pouvez faire vos mises à jour. J'ai écrit un court script pour écrire tout mon SQL de mise à jour basé sur le même nom de colonne (dans mon cas, j'avais besoin d'augmenter le CaseID de 1000000:

select 
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position

Enfin, réactivez l'intégrité référentielle, puis réactivez la colonne Identité sur la clé primaire.

Remarque: je vois des gens sur ces questions demander POURQUOI. Dans mon cas, je dois fusionner les données d'une deuxième instance de production dans une base de données maître afin de pouvoir arrêter la deuxième instance. J'ai juste besoin de toutes les données PK / FK des opérations pour ne pas entrer en collision. Les FK de méta-données sont identiques.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.