Como atualizar a coluna de identidade no SQL Server?


195

Eu tenho o banco de dados do SQL Server e quero alterar a coluna de identidade porque ela começou com um grande número 10010e está relacionada a outra tabela, agora tenho 200 registros e quero corrigir esse problema antes que os registros aumentem.

Qual é a melhor maneira de alterar ou redefinir esta coluna?

Respostas:


269

Você não pode atualizar a coluna de identidade.

O SQL Server não permite atualizar a coluna de identidade, diferente do que você pode fazer com outras colunas com uma instrução de atualização.

Embora existam algumas alternativas para atingir um tipo semelhante de requisito.

  • Quando o valor da coluna Identity precisar ser atualizado para novos registros

Use DBCC CHECKIDENT que verifica o valor atual da identidade da tabela e, se necessário, altera o valor da identidade.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Quando o valor da coluna Identity precisa ser atualizado para registros existentes

Use IDENTITY_INSERT, que permite que valores explícitos sejam inseridos na coluna de identidade de uma tabela.

SET IDENTITY_INSERT YourTable {ON|OFF}

Exemplo:

-- 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 Redefina o próximo novo registro, mas o que eu quero agora para alterar os registros existentes.
— Abdulsalam Elsharif

você pode dar exemplo por favor?
— Abdulsalam Elsharif

38
@sachin este não está atualizando uma identidade existente isso é inserir manualmente
— Phill Greggan

3
@PhillGreggan sim, esta é a melhor solução possível para conseguir isso. Você não pode atualizar a coluna Identidade ao atualizar as normais.
— Sachin

17
Esta resposta aceita não responde à pergunta, que é como atualizar uma coluna de identidade (por exemplo UPDATE YourTable SET IdentityCol = 13). SET IDENTITY_INSERT YourTable ONpermite apenas INSERTs, não UPDATEs.
— Ian Boyd

61

Se você acertou sua pergunta, você quer fazer algo como

update table
set identity_column_name = some value

Deixe-me dizer-lhe, não é um processo fácil e não é aconselhável usá-lo, pois pode haver alguns foreign keyassociados.

Mas aqui estão os passos para fazê-lo, por favor, tome um back-upda tabela

Etapa 1- Selecione a visualização de design da tabela

insira a descrição da imagem aqui

Etapa 2- Desative a coluna de identidade

insira a descrição da imagem aqui

Agora você pode usar a updateconsulta.

Agora, redoas etapas 1 e 2 e ative a coluna identidade

Referência


1
Eu tenho outra tabela relacionada com esta tabela, I coisa que eu não posso fazer isso
— Abdulsalam Elsharif

4
Daí a afirmação não é aconselhável :)
— Luv

3
@AbdusalamElsherif Mas você perguntou como alterar a coluna de identidade.
— Paparazzo

@luv pelo menos você respondeu à pergunta que foi feita #
— Phill Greggan

Eu uso este procedimento para definir a identificação no meu banco de dados de desenvolvimento. Seria bom se houvesse um comando que me permita fazer isso de qualquer maneira, mas isso funciona.
— Jeff Davis

56

Você precisa

set identity_insert YourTable ON

Em seguida, exclua sua linha e reinsira-a com uma identidade diferente.

Depois de concluir a inserção, não se esqueça de desativar o identity_insert

set identity_insert YourTable OFF

Isso é muito mais fácil e seguro do que desativar o Identity da coluna!
— Protector one

Isso é mais seguro e fácil para um pequeno número de registros, mas não responde adequadamente à pergunta. Desativar a identidade, embora mais perigoso e às vezes impossível, permite que você atualize a coluna de identidade.
— 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
Apenas uma dica de desempenho, se a tabela for muito grande, em vez de excluir uma tabela, faça uma Truncate Table yourTable. É instantâneo. Cuidado, porém, não é possível voltar com truncado, pois não está registrado.
— Kuklei 27/10/19


5

copie sua tabela para uma nova tabela sem coluna de identidade.

    select columns into newtable from yourtable

adicione uma coluna de identidade à nova tabela com nova semente e faça-a como chave primária

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = forneça a tabela que você deseja redefinir o valor

value = valor inicial como zero, para iniciar a coluna de identidade com 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

Ao usar o Identity_Insert, não se esqueça de incluir os nomes das colunas, porque o sql não permitirá que você insira sem especificá-los


2

Você também pode usar SET IDENTITY INSERTpara permitir inserir valores em uma coluna de identidade.

Exemplo:

SET IDENTITY_INSERT dbo.Tool ON
GO

E então você pode inserir em uma coluna de identidade os valores necessários.


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

No entanto, o código acima funciona apenas se não houver relação de chave estrangeira primária


1

Solução completa para programadores em C # usando o construtor de comandos

Primeiro de tudo, você precisa conhecer esses fatos:

  • De qualquer forma, você não pode modificar uma coluna de identidade; portanto, é necessário excluir a linha e adicionar novamente com a nova identidade.
  • Você não pode remover a propriedade de identidade da coluna (você precisaria remover para a coluna)
  • O construtor de comandos customizado de .net sempre ignora a coluna de identidade, portanto, não é possível usá-la para essa finalidade.

Então, uma vez sabendo disso, o que você precisa fazer é. Programe sua própria instrução SQL Insert ou programe seu próprio construtor de comandos insert. Ou use este programado para você. Dada uma DataTable, gera o 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

Resolvi esse problema primeiro usando o DBCC e depois usando o insert. Por exemplo, se sua mesa é

Primeiro, defina o novo valor atual do ID na tabela como NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

então você pode usar

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

Isso duplicaria todos os seus registros, mas usando o novo valor de IDCol começando como NEW_RESEED_VALUE. Em seguida, você pode remover linhas duplicadas com maior valor de ID depois de remover / mover as referências de chave estrangeira, se houver.


1
Essa é uma ideia decente, mas o New_reseed_value é a semente atual, e o próximo número que será usado será 1 a mais que esse valor. Então se você quer a próxima linha inserida seja de identidade 10, então NEW_RESEED_VALUE deve ser definido como 9.
— LarryBud

0

Você pode criar uma nova tabela usando o seguinte código.

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

Em seguida, exclua o banco de dados antigo e renomeie o novo banco de dados para o nome do banco de dados antigo. Nota : essa coluna1 e coluna2 representam todas as colunas da sua tabela antiga que você deseja manter na sua nova tabela.


0

Se você precisar especificamente alterar o valor da chave primária para um número diferente (ex 123 -> 1123). A propriedade de identidade bloqueia a alteração de um valor PK. Definir Identity_insert não vai funcionar. Não é recomendável fazer uma inserção / exclusão se houver exclusões em cascata (a menos que você desative a verificação de integridade referencial).

Este script desativará a identidade em um 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

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

Em seguida, você pode definir os relacionamentos para que eles atualizem as referências de chave estrangeira. Ou então, você precisa desativar a imposição de relacionamento. Este link SO mostra como: Como as restrições de chave estrangeira podem ser temporariamente desabilitadas usando o T-SQL?

Agora, você pode fazer suas atualizações. Eu escrevi um script curto para escrever toda a minha atualização SQL com base no mesmo nome de coluna (no meu caso, eu precisava aumentar o CaseID em 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

Por fim, reative a integridade referencial e, em seguida, reative a coluna Identidade na chave primária.

Nota: Eu vejo algumas pessoas nessas perguntas perguntando POR QUE. No meu caso, tenho que mesclar dados de uma segunda instância de produção em um banco de dados mestre para poder desligar a segunda instância. Eu só preciso de todos os PK / FKs de dados de operações para não colidir. Os FKs de metadados são idênticos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.