reiniciar - reseed identity sql server 2012
DBCC CHECKIDENT establece la identidad en 0 (8)
Estoy usando este código para restablecer la identidad en una tabla:
DBCC CHECKIDENT(''TableName'', RESEED, 0)
Esto funciona bien la mayor parte del tiempo, con la primera inserción inserto 1 en la columna Id. Sin embargo, si dejo caer el db y lo vuelvo a crear (usando los scripts que he escrito) y luego llamo a DBCC CHECKIDENT, el primer elemento insertado tendrá un ID de 0.
¿Algunas ideas?
EDITAR: Después de investigar descubrí que no leí la documentación correctamente: http://msdn.microsoft.com/en-us/library/aa258817(SQL.80).aspx - "El valor de identidad actual se establece en new_reseed_value. Si no se han insertado filas en la tabla desde que se creó, la primera fila insertada después de ejecutar DBCC CHECKIDENT usará new_reseed_value como identidad. De lo contrario, la siguiente fila insertada usará new_reseed_value + 1. "
Cambiar declaración a
DBCC CHECKIDENT(''TableName'', RESEED, 1)
Esto comenzará desde 2 (o 1 cuando vuelva a crear la tabla), pero nunca será 0.
Vea también aquí: http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/06/26/fun-with-dbcc-chekident.aspx
Este es un comportamiento documentado, ¿por qué ejecuta CHECKIDENT si recrea la tabla, en ese caso omita el paso o use TRUNCATE (si no tiene relaciones FK)?
Como señaló en su pregunta, es un comportamiento documentado . Todavía me parece extraño. Utilizo para repoblar la base de datos de prueba y aunque no confío en los valores de los campos de identidad, fue un poco molesto tener diferentes valores al llenar la base de datos por primera vez desde cero y después de eliminar todos los datos y volver a llenarlos.
Una posible solución es usar truncar para limpiar la tabla en lugar de eliminar. Pero luego debe eliminar todas las restricciones y volver a crearlas después
De esa forma, siempre se comporta como una tabla recién creada y no hay necesidad de llamar a DBCC CHECKIDENT. El primer valor de identidad será el especificado en la definición de la tabla y será el mismo sin importar si inserta los datos por primera vez o para la N-ésima.
Tiene razón en lo que escribe en la edición de su pregunta.
Después de ejecutar DBCC CHECKIDENT(''TableName'', RESEED, 0)
:
- Las tablas recién creadas comenzarán con la identidad 0
- Las tablas existentes continuarán con la identidad 1
La solución está en el script a continuación, es una especie de pobre-hombre-truncado :)
-- Remove all records from the Table
DELETE FROM TableName
-- Use sys.identity_columns to see if there was a last known identity value
-- for the Table. If there was one, the Table is not new and needs a reset
IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = ''TableName'' AND last_value IS NOT NULL)
DBCC CHECKIDENT (TableName, RESEED, 0);
Hice esto como un experimento para restablecer el valor a 0 porque quiero que mi primera columna de identidad sea 0 y esté funcionando.
dbcc CHECKIDENT(MOVIE,RESEED,0)
dbcc CHECKIDENT(MOVIE,RESEED,-1)
DBCC CHECKIDENT(MOVIE,NORESEED)
USE AdventureWorks2012;
GO
DBCC CHECKIDENT (''Person.AddressType'', RESEED, 0);
GO
AdventureWorks2012=Your databasename
Person.AddressType=Your tablename
Lo he usado en SQL para configurar IDENTIDAD a un valor particular:
DECLARE @ID int = 42;
DECLARE @TABLENAME varchar(50) = ''tablename''
DECLARE @SQL nvarchar(1000) = ''IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = ''''''+@TABLENAME+'''''' AND last_value IS NOT NULL)
BEGIN
DBCC CHECKIDENT(''+@TABLENAME+'', RESEED,'' + CONVERT(VARCHAR(10),@ID-1)+'');
END
ELSE
BEGIN
DBCC CHECKIDENT(''+@TABLENAME+'', RESEED,'' + CONVERT(VARCHAR(10),@ID)+'');
END'';
EXEC (@SQL);
Y esto en C # para establecer un valor particular: -
SetIdentity(context, "tablename", 42);
.
.
private static void SetIdentity(DbContext context, string table,int id)
{
string str = "IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = ''" + table
+ "'' AND last_value IS NOT NULL)/nBEGIN/n";
str += "DBCC CHECKIDENT(''" + table + "'', RESEED," + (id - 1).ToString() + ");/n";
str += "END/nELSE/nBEGIN/n";
str += "DBCC CHECKIDENT(''" + table + "'', RESEED," + (id).ToString() + ");/n";
str += "END/n";
context.Database.ExecuteSqlCommand(str);
}
Esto se basa en las respuestas anteriores y siempre se asegura de que el siguiente valor sea 42 (en este caso).
Parece ridículo que no pueda establecer / restablecer una columna de identidad con un solo comando para cubrir ambos casos de si la tabla ha tenido registros insertados o no. ¡No podía entender el comportamiento que estaba experimentando hasta que tropecé con la pregunta anterior sobre SO! Mi solución - fea pero funciona - es verificar explícitamente la tabla sys.identity_columns.last_value que le dice si la tabla ha tenido o no registros insertados, y llamar al comando DBCC CHECKIDENT apropiado en cada caso: DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = ''MyTable'')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT (''MyTable'', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT (''MyTable'', RESEED, @lastValUsed); END
DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = ''MyTable'')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT (''MyTable'', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT (''MyTable'', RESEED, @lastValUsed); END