¿Cómo actualizar la columna de identidad en SQL Server?

195

Tengo una base de datos SQL Server y quiero cambiar la columna de identidad porque comenzó con un gran número 10010y está relacionada con otra tabla, ahora tengo 200 registros y quiero solucionar este problema antes de que aumenten los registros.

¿Cuál es la mejor manera de cambiar o restablecer esta columna?

Abdulsalam Elsharif
fuente

Respuestas:

269

No puede actualizar la columna de identidad.

SQL Server no permite actualizar la columna de identidad a diferencia de lo que puede hacer con otras columnas con una declaración de actualización.

Aunque hay algunas alternativas para lograr un tipo similar de requisito.

  • Cuándo debe actualizarse el valor de la columna Identidad para nuevos registros

Use DBCC CHECKIDENT que verifica el valor de identidad actual para la tabla y, si es necesario, cambia el valor de identidad.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Cuándo se debe actualizar el valor de la columna de identidad para los registros existentes

Use IDENTITY_INSERT que permite insertar valores explícitos en la columna de identidad de una tabla.

SET IDENTITY_INSERT YourTable {ON|OFF}

Ejemplo:

-- 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
fuente
66
DBCC Restablece el próximo nuevo registro, pero lo que quiero ahora es cambiar los registros existentes.
Abdulsalam Elsharif
puedes dar ejemplo por favor?
Abdulsalam Elsharif
38
@sachin esto no está actualizando una IDENTIDAD existente que está insertando manualmente
Phill Greggan
3
@PhillGreggan sí, esta es la mejor solución posible para lograr esto. No puede actualizar la columna Identidad a medida que actualiza las normales.
Sachin
17
Esta respuesta aceptada no responde la pregunta, que es cómo actualizar una columna de identidad (por ejemplo UPDATE YourTable SET IdentityCol = 13). SET IDENTITY_INSERT YourTable ONsolo permite INSERT, no ACTUALIZACIONES.
Ian Boyd
61

Si tu pregunta es correcta, quieres hacer algo como

update table
set identity_column_name = some value

Déjame decirte que no es un proceso fácil y no es aconsejable usarlo, ya que puede haber algunos foreign keyasociados.

Pero aquí hay pasos para hacerlo, por favor tome una back-upmesa

Paso 1- Seleccione la vista de diseño de la tabla

ingrese la descripción de la imagen aquí

Paso 2- Desactiva la columna de identidad

ingrese la descripción de la imagen aquí

Ahora puedes usar la updateconsulta.

Ahora redoel paso 1 y el paso 2 y encienda la columna de identidad

Referencia

Luv
fuente
1
Tengo otra tabla relacionada con esta tabla, creo que no puedo hacer eso
Abdulsalam Elsharif
44
De ahí la afirmación de que no es aconsejable :)
Luv
3
@AbdusalamElsherif Pero usted preguntó cómo cambiar la columna de identidad.
paparazzo
@luv al menos has respondido a la pregunta que se hizo
Phill Greggan
Utilizo este procedimiento para configurar la identificación en mi base de datos de desarrollo. Sería bueno si hubiera un comando que me permitiera hacerlo de todos modos, pero esto funciona.
Jeff Davis el
56

Necesitas

set identity_insert YourTable ON

Luego, elimine su fila y vuelva a insertarla con una identidad diferente.

Una vez que haya realizado la inserción, no se olvide de desactivar identity_insert

set identity_insert YourTable OFF
RSP
fuente
¡Esto es mucho más fácil y seguro que desactivar Identity para la columna!
Protector uno
Esto es más seguro y fácil para una pequeña cantidad de registros, pero no responde adecuadamente la pregunta. Desactivar la identidad, aunque es más peligroso y a veces imposible, le permite actualizar la columna de identidad.
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
fuente
1
Solo un consejo de rendimiento si la tabla es muy grande, en lugar de hacer una eliminación en la tabla, haga un Truncar tabla yourTable. Es instantáneo. Sin embargo, tenga cuidado, no retroceda con truncado ya que no está registrado.
kuklei
5

copie su tabla a una nueva tabla sin columna de identidad.

    select columns into newtable from yourtable

agregue una columna de identidad a newtable con nueva semilla y conviértala como clave principal

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY
user4002899
fuente
3
DBCC CHECKIDENT(table_name, RESEED, value)

nombre_tabla = proporcione el valor de la tabla que desea restablecer

valor = valor inicial para ser cero, para iniciar la columna de identidad con 1

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

Cuando use Identity_Insert, no olvide incluir los nombres de columna porque sql no le permitirá insertar sin especificarlos

befree2j
fuente
2

También puedes usar SET IDENTITY INSERT para permitirle insertar valores en una columna de identidad.

Ejemplo:

SET IDENTITY_INSERT dbo.Tool ON
GO

Y luego puede insertar en una columna de identidad los valores que necesita.

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

Sin embargo, el código anterior solo funciona si no hay una relación de clave primaria-externa

Jekin Kalariya
fuente
1

Solución completa para programadores de C # usando el generador de comandos

En primer lugar, debes conocer estos hechos:

  • En cualquier caso, no puede modificar una columna de identidad, por lo que debe eliminar la fila y volver a agregarla con una nueva identidad.
  • No puede eliminar la propiedad de identidad de la columna (debería eliminarla en la columna)
  • El generador de comandos personalizados de .net siempre omite la columna de identidad, por lo que no puede usarla para este propósito.

Entonces, una vez que sabes eso, lo que tienes que hacer es. Programe su propia instrucción de inserción SQL o programe su propio generador de comandos de inserción. O usa este que estoy programado para ti. Dada una tabla de datos, genera el script de inserción 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 ();
}
Juan_Mallorca
fuente
0

He resuelto este problema primero usando DBCC y luego usando insert. Por ejemplo si tu mesa es

En primer lugar, establezca el nuevo valor de ID actual en la tabla como NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

entonces puedes usar

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

Esto duplicaría todos sus registros pero utilizando un nuevo valor IDCol que comience como NEW_RESEED_VALUE. Luego, puede eliminar filas duplicadas de mayor valor de ID una vez que haya eliminado / movido sus referencias de clave externa, si las hubiera.

Softec
fuente
1
Esta es una idea decente, pero New_reseed_value es la semilla actual, y el siguiente número que se utilizará será 1 más que ese valor. Entonces, si desea que la siguiente fila insertada sea la identidad 10, entonces NEW_RESEED_VALUE debe establecerse en 9.
LarryBud
0

Puede crear una nueva tabla con el siguiente código.

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

Luego elimine el db antiguo y cambie el nombre del nuevo db al nombre del antiguo db. Nota : esa columna1 y columna2 representan todas las columnas de su tabla anterior que desea mantener en su tabla nueva.

Sean H. Worthington
fuente
0

Si necesita específicamente cambiar el valor de la clave primaria a un número diferente (por ejemplo, 123 -> 1123). La propiedad de identidad bloquea el cambio de un valor PK. Establecer Identity_insert no va a funcionar. No es recomendable realizar una inserción / eliminación si tiene eliminaciones en cascada (a menos que desactive la comprobación de integridad referencial).

Este script desactivará la identidad en una 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

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

A continuación, puede establecer las relaciones para que actualicen las referencias de clave externa. O bien, debe desactivar la aplicación de la relación. Este enlace SO muestra cómo: ¿Cómo se pueden deshabilitar temporalmente las restricciones de clave externa utilizando T-SQL?

Ahora puedes hacer tus actualizaciones. Escribí un script corto para escribir todo mi SQL de actualización basado en el mismo nombre de columna (en mi caso, necesitaba aumentar el CaseID en 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 último, vuelva a habilitar la integridad referencial y luego vuelva a habilitar la columna Identidad en la clave primaria.

Nota: veo que algunas personas en estas preguntas preguntan por qué. En mi caso, tengo que fusionar datos de una segunda instancia de producción en una base de datos maestra para poder cerrar la segunda instancia. Solo necesito todos los PK / FK de datos de operaciones para no colisionar. Los metadatos FK son idénticos.

Ken Forslund
fuente