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?

Abdulsalam Elsharif
fonte

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
Sachin
fonte
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

Luv
fonte
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
RSP
fonte
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
kuklei
fonte
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
user4002899
fonte
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

Yasmeen Ansari
fonte
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

befree2j
fonte
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.

DaveShaw
fonte
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

Jekin Kalariya
fonte
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 ();
}
Juan_Mallorca
fonte
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.

Softec
fonte
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.

Sean H. Worthington
fonte
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.

Ken Forslund
fonte