Creé una tabla en un DB que ya existe en otro DB. Inicialmente se rellenó con los datos antiguos de DB. El PK de la tabla tenía que recibir los valores que ya existen en esos registros, por lo que no podría ser autoincrement.
Ahora necesito que la nueva tabla tenga su PK como autoincremento. Pero, ¿cómo puedo hacer eso después de que el PK ya exista y tenga datos?
IDENTITY
?Respuestas:
La forma en que entiendo su pregunta es que tiene una tabla existente con una columna que hasta ahora se ha rellenado con valores manuales, y ahora desea (1) hacer que esta columna sea una
IDENTITY
columna y (2) asegurarse de queIDENTITY
comience desde el valor más reciente en las filas existentes.En primer lugar, algunos datos de prueba para jugar:
El objetivo es crear la columna de clave principal de la tabla
id
, unaIDENTITY
columna que comenzará en 21 para el siguiente registro que se inserte. Para este ejemplo, la columnaxyz
representa todas las otras columnas de la tabla.Antes de hacer nada, lea las advertencias al final de esta publicación.
En primer lugar, en caso de que algo salga mal:
Ahora, agreguemos una columna de trabajo temporal
id_temp
y configuremos esa columna a losid
valores de la columna existente :A continuación, debemos descartar la
id
columna existente (no puede simplemente "agregar" unaIDENTITY
a una columna existente, debe crear la columna como unaIDENTITY
). La clave principal también tiene que ir, porque la columna depende de ella.... y agregue la columna nuevamente, esta vez como
IDENTITY
, junto con la clave principal:Aquí es donde se pone interesante. Puede habilitar
IDENTITY_INSERT
en la tabla, lo que significa que puede definir manualmente los valores de unaIDENTITY
columna cuando inserta nuevas filas (sin embargo, no actualiza las filas existentes).Con ese conjunto,
DELETE
todas las filas de la tabla, pero las filas que está eliminando estánOUTPUT
en la misma tabla, pero con valores específicos para laid
columna (de la columna de copia de seguridad).Una vez hecho,
IDENTITY_INSERT
apague nuevamente.Suelte la columna temporal que agregamos:
Y finalmente, vuelva a colocar la
IDENTITY
columna, para que los siguientes registrosid
se reanuden después del número más alto existente en laid
columna:Verificando la tabla de ejemplo, el
id
número más alto es 20.Agregue otra fila y verifique su nuevo
IDENTITY
:En el ejemplo, la nueva fila tendrá
id=21
. Finalmente, si estás contento, confirma la transacción:Importante
Esta no es una operación trivial, y conlleva bastantes riesgos que debe tener en cuenta.
Haga esto en un entorno de prueba dedicado. Tener copias de seguridad. :)
Me gusta usarlo
BEGIN/COMMIT TRANSACTION
porque evita que otros procesos se enreden con la tabla mientras estás en medio de cambiarla, y te da la posibilidad de deshacer todo si algo sale mal. Sin embargo, cualquier otro proceso que intente acceder a su tabla antes de que haya confirmado su transacción terminará esperando. Esto puede ser bastante malo si tiene una mesa grande y / o está en un entorno de producción.OUTPUT .. INTO
no funcionará si su tabla de destino tiene restricciones de clave externa o cualquiera de una serie de otras características que no puedo recordar en la parte superior de mi cabeza. En su lugar, puede descargar los datos en una tabla temporal y luego volver a insertarlos en la tabla original. Es posible que pueda usar el cambio de partición (incluso si no usa particiones).Ejecute estas declaraciones una por una, no como un lote o en un procedimiento almacenado.
Intente pensar en otras cosas que pueden depender de la
id
columna que está soltando y volviendo a crear. Cualquier índice tendrá que descartarse y volver a crearse (como hicimos con la clave primaria). Recuerde escribir cada índice y restricción que necesitará recrear de antemano.Deshabilita cualquiera
INSERT
yDELETE
disparadores en la mesa.Si volver a crear la tabla es una opción:
Si volver a crear la tabla es una opción para usted, todo es mucho más simple:
id
columna como unIDENTITY
,IDENTITY_INSERT ON
para la mesa,IDENTITY_INSERT OFF
, yfuente
IDENTITY_INSERT ON
, rellenarlo y desactivarlo. Eso es lo que quería hacer, pero no sabía que MSSQL lo soportaba.Usar ACTUALIZAR, ELIMINAR o INSERTAR para mover datos puede llevar bastante tiempo y usar recursos (IO) tanto en datos como en archivos / discos de registro. Es posible evitar llenar el registro de transacciones con potencialmente muchos registros mientras se trabaja en una tabla grande: mediante el cambio de partición, solo se modifican los metadatos.
No hay movimiento de datos involucrados y, por lo tanto, esto se realiza muy rápido (casi instantáneo).
Tabla de muestra
La pregunta no muestra la tabla original DDL. El siguiente DDL se usará como ejemplo en esta respuesta:
Se agregan media docena de identificadores aleatorios ficticios de 0 a 15 con esta consulta:
Datos de ejemplo en
IdT
Nueva mesa con
IDENTITY(0, 1)
El único problema con
idT
es la falta de laIDENTITY(0, 1)
propiedad en la identificación. SeIDENTITY(0, 1)
crea una nueva tabla con una estructura similar :Aparte de
IDENTITY(0, 1)
,idT_Switch
es idéntico aidT
.Llaves extranjeras
idT
Deben eliminarse las claves foráneas activadas para permitir el uso de esta técnica.Interruptor de partición
Las tablas
idT
yidT_Switch
tienen una estructura compatible. En lugar de utilizarDELETE
,UPDATE
yINSERT
las declaraciones de mover filas deidT
aidT_Switch
o sobreidT
sí mismo,ALTER TABLE ... SWITCH
se puede utilizar:La única 'partición' de
PK_idT
(toda la tabla) se mueve aPK_idT_Switch
(y viceversa).idT
ahora contiene 0 filas yidT_Switch
contiene 6 filas.Puede encontrar la lista completa de requisitos de compatibilidad de origen y destino aquí:
Transferencia de datos eficientemente mediante el cambio de partición
Tenga en cuenta que este uso de
SWITCH
no requiere Enterprise Edition, porque no hay particiones explícitas. Se considera que una tabla sin particiones es una tabla con una única partición desde SQL Server 2005 en adelante.Reemplazar
idT
idT
ahora está vacío e inútil y puede descartarse:idT_Switch
se puede renombrar y reemplazará laidT
tabla anterior:Llaves extranjeras
Las claves externas se pueden agregar nuevamente a la nueva
idT
tabla. Cualquier otra cosa que se haya eliminado previamenteidT
para hacer que las tablas sean compatibles para el cambio también deberá rehacerse.Reseed
Este comando devuelve 0. La tabla idT contiene 6 filas con MAX (id) = 15. Se puede usar DBCC CHECKIDENT (nombre_tabla) :
Como 15 es mayor que 0, se reiniciará automáticamente sin buscar MAX (id):
IDENT_CURRENT ahora devuelve 15 .
Probar y agregar datos
Una
INSERT
declaración simple :Agrega esta fila:
La
id
columna ahora está usando la identidad y el valor recién insertado es de hecho 16 (15 + 1).Más información
Hay una pregunta y respuesta relacionada con más antecedentes sobre la
SWITCH
técnica aquí:¿Por qué no se admite la eliminación de la propiedad Identity en una columna?
fuente
Si desea comenzar con un nuevo valor de identidad, debe reiniciar su identidad. Echa un vistazo a la documentación para
CHECKIDENT
fuente
ENABLE y DISABLE IDENTITY_INSERT
Si su tabla es TABLE_A entonces
fuente