Come aggiornare la colonna identità in SQL Server?


196

Ho un database SQL Server e voglio cambiare la colonna identità perché è iniziata con un numero elevato 10010ed è correlata a un'altra tabella, ora ho 200 record e voglio risolvere questo problema prima che aumenti.

Qual è il modo migliore per modificare o ripristinare questa colonna?

Risposte:


270

Non è possibile aggiornare la colonna identità.

SQL Server non consente di aggiornare la colonna identità diversamente da come è possibile fare con altre colonne con un'istruzione update.

Sebbene ci siano alcune alternative per raggiungere un tipo simile di requisito.

  • Quando il valore della colonna Identità deve essere aggiornato per i nuovi record

Utilizzare DBCC CHECKIDENT che controlla il valore di identità corrente per la tabella e, se necessario, modifica il valore di identità.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Quando il valore della colonna Identità deve essere aggiornato per i record esistenti

Utilizzare IDENTITY_INSERT che consente l'inserimento di valori espliciti nella colonna identità di una tabella.

SET IDENTITY_INSERT YourTable {ON|OFF}

Esempio:

-- 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 Reimposta il nuovo record successivo, ma quello che voglio ora modificare i record esistenti.
Abdulsalam Elsharif,

puoi fare un esempio per favore?
Abdulsalam Elsharif,

38
@sachin questo non aggiorna un'IDENTITÀ esistente che si sta inserendo manualmente
Phill Greggan,

3
@PhillGreggan sì, questa è la migliore soluzione possibile per raggiungere questo obiettivo. Non è possibile aggiornare la colonna Identità mentre si aggiornano quelle normali.
Sachin,

17
Questa risposta accettata non risponde alla domanda, ovvero come aggiornare una colonna di identità (ad es UPDATE YourTable SET IdentityCol = 13.). SET IDENTITY_INSERT YourTable ONconsente solo INSERTI, non AGGIORNAMENTI.
Ian Boyd,

62

Se hai la domanda giusta, vuoi fare qualcosa del genere

update table
set identity_column_name = some value

Lascia che te lo dica, non è un processo facile e non è consigliabile utilizzarlo, poiché potrebbero esserci alcuni foreign keyassociati.

Ma ecco i passaggi per farlo, per favore prendi un back-uptavolo

Passaggio 1- Selezionare la vista di progettazione della tabella

inserisci qui la descrizione dell'immagine

Passaggio 2: disattivare la colonna identità

inserisci qui la descrizione dell'immagine

Ora puoi usare la updatequery.

Ora redoil passaggio 1 e il passaggio 2 e Attiva la colonna identità

Riferimento


1
Ho un altro tavolo correlato a questo tavolo, cosa che non posso farlo
Abdulsalam Elsharif,

4
Quindi l'affermazione non è consigliabile :)
Luv

3
@AbdusalamElsherif Ma hai chiesto come modificare la colonna identità.
paparazzo,

@luv almeno hai risposto alla domanda che è stata posta
Phill Greggan il

Uso questa procedura per impostare l'id nel mio database di sviluppo. Sarebbe bello se ci fosse un comando che mi permetta di farlo comunque, ma funziona.
Jeff Davis,

56

Devi

set identity_insert YourTable ON

Quindi eliminare la riga e reinserirla con identità diversa.

Una volta terminato l'inserimento, non dimenticare di disattivare identity_insert

set identity_insert YourTable OFF

È molto più semplice e sicuro che disattivare Identity per la colonna!
Protector un

Questo è più sicuro e facile per un numero limitato di record, ma non risponde correttamente alla domanda. La disattivazione dell'identità, sebbene più pericolosa e talvolta impossibile, ti consente di aggiornare la colonna 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
Solo un suggerimento sulle prestazioni se la tabella è molto grande, invece di eseguire un'eliminazione sulla tabella esegui una tabella di troncamento della tabella. È istantaneo. Attenzione però, non tornare indietro con troncato in quanto non è registrato.
Kuklei,


5

copia la tabella in una nuova tabella senza colonna identità.

    select columns into newtable from yourtable

aggiungi una colonna di identità a newtable con nuovo seed e rendila una chiave primaria

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = indica la tabella per cui vuoi ripristinare il valore

valore = valore iniziale da zero, per iniziare la colonna identità con 1


3
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

Quando si utilizza Identity_Insert, non dimenticare di includere i nomi delle colonne perché sql non ti permetterà di inserire senza specificarli


2

È inoltre possibile utilizzare SET IDENTITY INSERTper consentire l'inserimento di valori in una colonna identità.

Esempio:

SET IDENTITY_INSERT dbo.Tool ON
GO

E quindi è possibile inserire in una colonna identità i valori necessari.


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

Tuttavia il codice sopra funziona solo se non esiste una relazione chiave primaria-esterna


1

Soluzione completa per programmatori C # utilizzando il generatore di comandi

Prima di tutto, devi conoscere questi fatti:

  • In ogni caso, non è possibile modificare una colonna identità, quindi è necessario eliminare la riga e aggiungere nuovamente con nuova identità.
  • Non puoi rimuovere la proprietà identità dalla colonna (dovresti rimuoverla)
  • Il generatore di comandi personalizzato da .net salta sempre la colonna identità, quindi non è possibile utilizzarla per questo scopo.

Quindi, una volta che lo sai, quello che devi fare è. Programmare la propria istruzione SQL Insert o programmare il proprio generatore di comandi insert. O usa questo che ho programmato per te. Dato un DataTable, genera lo script Inserisci SQL:

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

Ho risolto questo problema prima usando DBCC e poi usando insert. Ad esempio se il tuo tavolo è

Innanzitutto imposta il nuovo valore ID corrente sulla tabella come NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

allora puoi usare

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

Ciò duplicherebbe tutti i tuoi record ma usando il nuovo valore IDCol a partire da NEW_RESEED_VALUE. È quindi possibile rimuovere le righe duplicate di valore ID superiore dopo aver rimosso / spostato i riferimenti di chiave esterna, se presenti.


1
Questa è un'idea decente, ma New_reseed_value è il seme corrente e il numero successivo che verrà utilizzato sarà 1 in più di quel valore. Quindi se vuoi che la prossima riga inserita sia l'identità 10, NEW_RESEED_VALUE deve essere impostato su 9.
LarryBud,

0

È possibile creare una nuova tabella utilizzando il seguente codice.

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

Quindi eliminare il vecchio db e rinominare il nuovo db con il nome del vecchio db. Nota : quella colonna1 e colonna2 rappresentano tutte le colonne della vecchia tabella che desideri conservare nella nuova tabella.


0

Se è necessario modificare in modo specifico il valore della chiave primaria in un numero diverso (ad es. 123 -> 1123). La proprietà identity blocca la modifica di un valore PK. Impostare Identity_insert non funzionerà. Non è consigliabile eseguire un inserimento / eliminazione se si dispone di eliminazioni a cascata (a meno che non si disattivi il controllo di integrità referenziale).

Questo script disattiva l'identità su 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

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

Successivamente, puoi impostare le relazioni in modo che aggiornino i riferimenti alle chiavi esterne. Altrimenti devi disattivare l'applicazione delle relazioni. Questo link SO mostra come: Come si possono disabilitare temporaneamente i vincoli di chiave esterna usando T-SQL?

Ora puoi fare i tuoi aggiornamenti. Ho scritto un breve script per scrivere tutto il mio aggiornamento SQL basato sullo stesso nome di colonna (nel mio caso, avevo bisogno di aumentare il CaseID di 1.000.000:

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

Infine, riattiva l'integrità referenziale e quindi riattiva la colonna Identità sulla chiave primaria.

Nota: vedo alcune persone su queste domande chiedersi PERCHÉ. Nel mio caso, devo unire i dati di una seconda istanza di produzione in un DB master in modo da poter chiudere la seconda istanza. Ho solo bisogno di tutti i dati PK / FK dei dati operativi per non scontrarmi. Gli FK di metadati sono identici.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.