152

Tengo una base de datos MS SQL 2005 con una tabla Test con la columna ID. ID es una columna de identidad.¿Cómo cambiar los valores de la columna de identidad de forma programática?

tengo filas en esta tabla y todos ellos tienen su correspondiente valor autoincremented ID.

Ahora me gustaría cambiar cada ID en esta tabla como la siguiente:

ID = ID + 1 

Pero cuando hago esto me da un error:

Cannot update identity column 'ID'. 

He intentado esto:

ALTER TABLE Test NOCHECK CONSTRAINT ALL 
set identity_insert ID ON 

Pero esto no resuelve el problema.

Necesito tener identidad configurado para esta columna, pero tengo que cambiar los valores, así de vez en cuando. Entonces mi pregunta es cómo lograr esta tarea.

Respuesta

212

Necesitas

set identity_insert YourTable ON 

A continuación, elimine su fila y vuelva a insertarlo con diferente identidad.

Una vez hecho el inserto no se olvide de activar identity_insert fuera

set identity_insert YourTable OFF 
+130

establecer esto funcionará sólo cuando la inserción de datos y no cuando se actualiza. La instrucción UPDATE aún fallará. –

+29

Para una actualización, debe eliminar y volver a insertar. No hay otra manera. – ashes999

+1

@MartinSmith su solución parece demasiado larga.Ser capaz de hacerlo en dos pasos (identidad desactivada, eliminar/insertar, identidad activada) es mucho más efectivo. – ashes999

26

A través de la interfaz de usuario en el administrador de SQL Server 2005, cambie la columna quitar el autonumber (identidad) Propiedad de la columna (seleccione la tabla haciendo clic derecho sobre él y seleccione "Diseño").

A continuación, ejecute la consulta:

UPDATE table SET Id = Id + 1 

luego ir y añadir la propiedad autonumber de nuevo a la columna.

+4

Y cómo hacer esto a partir del código? –

+3

Si realiza el cambio manualmente, puede solicitar al gerente que genere el script SQL para el cambio (menú del diseñador de tablas, generar secuencia de comandos de cambio). Para este cambio crea una nueva tabla y copia los datos, luego elimina el original. –

+2

@tomaszs - un ejemplo de código que también es más eficiente, ya que no vuelve a generar la tabla física en absoluto (esto sería hacerlo dos veces) es en mi respuesta tardía [aquí] (http://stackoverflow.com/a/17249583/ 73226) –

4

Si la columna no es una PK siempre se puede crear una nueva columna en la tabla con los números incrementados, deje caer el original y luego alterar el nuevo ser el antiguo.

curiosidad de por qué es posible que tenga que hacer esto ... más que he tenido futz con columnas de identidad era para rellenar los números y yo sólo terminó mediante DBCC CHECKIDENT (nombre de tabla, RESEED, newnextnumber)

¡buena suerte!

1

Identidad modificador puede fallar dependiendo de una serie de factores, que giran principalmente en torno a los objetos/relaciones vinculadas a la columna id. Parece que el diseño de bases de datos es un problema aquí, ya que los identificadores rara vez o nunca deberían cambiar (estoy seguro de que tiene sus razones y está implementando los cambios). Si realmente necesita cambiar los id de vez en cuando, le sugiero que cree una nueva columna ficticia que no sea la clave principal/autonumber que puede administrar usted mismo y generar a partir de los valores actuales. Alternativamente, la idea de Chrisotphers anterior sería mi otra sugerencia si tienes problemas para permitir el inserto de identidad.

Buena suerte

PS no está fallando debido a que el orden secuencial que se está ejecutando en está intentando actualizar un valor en la lista a un elemento que ya existe en la lista de ID? agarrando pajitas, quizás agregue el número de filas + 1, entonces si eso funciona, restar el número de filas: -S

18

En primer lugar, la configuración de IDENTITY_INSERT activada o desactivada para ese asunto no funcionará para lo que necesita (es utilizado para insertar nuevos valores, como tapar huecos).

Realizando la operación a través de la GUI solo crea una tabla temporal, copia todos los datos en una nueva tabla sin un campo de identidad, y cambia el nombre de la tabla.

1

Si necesita cambiar los ID ocasionalmente, probablemente sea mejor no usar una columna de identidad. En el pasado, implementamos campos de autonumeración manualmente usando una tabla de "Contadores" que rastrea el siguiente ID para cada tabla. El IIRC lo hicimos porque las columnas de identidad estaban causando daños en la base de datos en SQL2000, pero el hecho de poder cambiar los identificadores ocasionalmente era útil para las pruebas.

6

DBCC CHECKIDENT ('databasename.dbo.orders', RESEED, 999) puede cambiar cualquier número de columna de identidad con este comando, y también puede comenzar ese número de campo de cada número que desee.por ejemplo en mi comando pido que empiece desde 1000 (999 + 1) espero que sea suficiente ... buena suerte

9

Esto puede hacerse usando una tabla temporal.

La idea

  • limitaciones desactivar (en caso de que su ID es referenciada por una clave externa)
  • crear una tabla temporal con el nuevo ID
  • borrar el contenido de la tabla
  • copia de los datos de la tabla copiada a su tabla original
  • habilitar restricciones deshabilitadas previsiblemente

consultas SQL

digamos que su mesa de test tienen dos columnas adicionales (column2 y column3) y que hay 2 mesas que tienen las claves externas referencia test llamada foreign_table1 y foreign_table2 (debido a problemas de la vida real nunca son simples).

alter table test nocheck constraint all; 
alter table foreign_table1 nocheck constraint all; 
alter table foreign_table2 nocheck constraint all; 
set identity_insert test on; 

select id + 1 as id, column2, column3 into test_copy from test v; 
delete from test; 
insert into test(id, column2, column3) 
select id, column2, column3 from test_copy 

alter table test check constraint all; 
alter table foreign_table1 check constraint all; 
alter table foreign_table2 check constraint all; 
set identity_insert test off; 
drop table test_copy; 

Eso es todo.

0

Vi un buen artículo que me ayudó en el último momento ... Estaba tratando de insertar algunas filas en una tabla que tenía una columna de identidad pero lo hice incorrectamente y tengo que borrar de nuevo. Una vez que eliminé las filas, mi columna de identidad cambió. Estaba intentando encontrar una forma de actualizar la columna que se insertó, pero no tuve suerte. Así, mientras que la búsqueda en Google encontró un enlace ..

  1. suprimido el columnas que se insertan erróneamente
  2. Uso de inserción fuerza utilizando la identidad de encendido/apagado (se explica más adelante)

http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column-how-do-i-update-the-value-of-an.aspx

+0

Sin embargo, no estoy seguro de que realmente haya respondido la pregunta aquí. –

39

IDENTITY los valores de la columna son inmutables.

Sin embargo, es posible cambiar los metadatos de tabla para quitar la propiedad IDENTITY, hacer la actualización, a continuación, cambiar de nuevo.

Asumiendo la siguiente estructura

CREATE TABLE Test 
(
ID INT IDENTITY(1,1) PRIMARY KEY, 
X VARCHAR(10) 
) 

INSERT INTO Test 
OUTPUT INSERTED.* 
SELECT 'Foo' UNION ALL 
SELECT 'Bar' UNION ALL 
SELECT 'Baz' 

A continuación, puede hacer

/*Define table with same structure but no IDENTITY*/ 
CREATE TABLE Temp 
(
ID INT PRIMARY KEY, 
X VARCHAR(10) 
) 

/*Switch table metadata to new structure*/ 
ALTER TABLE Test SWITCH TO Temp; 

/*Do the update*/ 
UPDATE Temp SET ID = ID + 1; 

/*Switch table metadata back*/ 
ALTER TABLE Temp SWITCH TO Test; 

/*ID values have been updated*/ 
SELECT * 
FROM Test 

/*Safety check in case error in preceding step*/ 
IF NOT EXISTS(SELECT * FROM Temp) 
    DROP TABLE Temp /*Drop obsolete table*/ 

En SQL Server 2012 que es posible tener una columna de incremento automático, que también se puede actualizar más directa con SEQUENCES

CREATE SEQUENCE Seq 
    AS INT 
    START WITH 1 
    INCREMENT BY 1 

CREATE TABLE Test2 
(
ID INT DEFAULT NEXT VALUE FOR Seq NOT NULL PRIMARY KEY, 
X VARCHAR(10) 
) 

INSERT INTO Test2(X) 
SELECT 'Foo' UNION ALL 
SELECT 'Bar' UNION ALL 
SELECT 'Baz' 

UPDATE Test2 SET ID+=1 
+0

+1 para la respuesta resbaladiza y la información sobre secuencias en SQL Server 2012. –

+1

Muy pulido. Aprender algo nuevo todos los días (por cierto, probé esto en SQLExpress; a pesar de que SWITCH TO no usa partición, aparentemente). Tenga en cuenta que la tabla tiene que coincidir casi exactamente (índices, FK, etc.) –

+0

¿Funciona el método de conmutación cuando tiene PK, FK, índice y vistas construidos sobre la tabla original? ¿Romperán al usar este método? –

1

puede insertar nuevas filas con mod valores ified y luego eliminar las filas antiguas. Siguiendo el ejemplo de cambio de ID sea igual extranjera clave PERSONID

SET IDENTITY_INSERT [PersonApiLogin] ON 

INSERT INTO [PersonApiLogin](
     [Id] 
     ,[PersonId] 
     ,[ApiId] 
     ,[Hash] 
     ,[Password] 
     ,[SoftwareKey] 
     ,[LoggedIn] 
     ,[LastAccess]) 
SELECT [PersonId] 
     ,[PersonId] 
     ,[ApiId] 
     ,[Hash] 
     ,[Password] 
     ,[SoftwareKey] 
     ,[LoggedIn] 
     ,[LastAccess] 
FROM [db304].[dbo].[PersonApiLogin] 
GO 

DELETE FROM [PersonApiLogin] 
WHERE [PersonId] <> ID 
GO 
SET IDENTITY_INSERT [PersonApiLogin] OFF 
GO 
0

Muy bonito pregunta, primero tenemos que en la IDENTITY_INSERT para la tabla específico, después de que ejecute la consulta de inserción (debe especificar el nombre de la columna)

Nota: Después de editar la columna de la identidad, no se olvide de fuera la IDENTITY_INSERT. Si no lo ha hecho, no podrá Editar la columna de identidad para ninguna otra tabla.

SET IDENTITY_INSERT Emp_tb_gb_Menu ON 
    INSERT Emp_tb_gb_Menu(MenuID) VALUES (68) 
SET IDENTITY_INSERT Emp_tb_gb_Menu OFF 

http://allinworld99.blogspot.com/2016/07/how-to-edit-identity-field-in-sql.html

1

Primera guardar todos los ID y modificar mediante programación a los valores que Wan't, a continuación, eliminarlos de la base de datos y luego insertarlos de nuevo usando algo similar:

use [Name.Database] 
go 
set identity_insert [Test] ON 
insert into [dbo].[Test] 
      ([Id]) 
    VALUES 
      (2) 
set identity_insert [Test] OFF 

Para uso de inserción a granel:

use [Name.Database] 
go 
set identity_insert [Test] ON 
BULK INSERT [Test] 
FROM 'C:\Users\Oscar\file.csv' 
WITH (FIELDTERMINATOR = ';', 
     ROWTERMINATOR = '\n', 
     KEEPIDENTITY) 
set identity_insert [Test] OFF 

Datos de muestra del archivo.csv:

2; 
3; 
4; 
5; 
6; 

Si no se establece identity_insert en off obtendrá el siguiente error:

Cannot insert explicit value for identity column in table 'Test' when IDENTITY_INSERT is set to OFF.

Cuestiones relacionadas