¿Por qué no se admite la eliminación de la propiedad Identity en una columna?

11

He leído que después de SQL Server 2000, se eliminó la capacidad de "desidentificar" una columna de identidad. Y que esto era "Por diseño" (no solo una característica faltante).

Aquí hay un ejemplo que encontré en un blog . Implica actualizar las tablas del sistema. (Y esa capacidad se eliminó después de SQL Server 2000). Entiendo que hacer esto a través de tablas del sistema no es una buena idea. Me pregunto por qué no existe una característica para hacer esto de otra manera.

Trabajar alrededor de esto me va a causar una cantidad considerable de trabajo. (Copiar muchos cientos de millones de filas en nuevas tablas en un entorno intolerante de tiempo de inactividad).

Así que pensé en preguntar "por qué".

¿Qué cambió en Sql Server 2005 y versiones posteriores que hicieron de esto algo malo? ¿O siempre fue malo y simplemente no se bloqueó?

¿Qué "mejor práctica" (o principio similar) se violaría al hacer que una columna de identidad vuelva a ser una columna normal?

-

Actualización para responder la solicitud de "por qué estoy haciendo esto":
Este es un resumen de muy alto nivel: voy a comenzar a agregar particiones a mis tablas. (Para poder archivar / purgar datos antiguos). Todo eso es fácil. Pero ocasionalmente necesito mover un registro a una partición diferente para que no se elimine (cuando aparece una partición para archivar / eliminar). (Estoy haciendo que mi columna de partición aumente en 2 para que siempre haya espacio para mover la fila a una partición diferente).

Pero si la columna de partición es una columna de identidad, entonces tengo que eliminar y volver a insertar el valor (no hay forma de actualizar el valor de una columna de identidad). Lo que causa problemas con la replicación.

Por lo tanto, quiero usar una secuencia en lugar de una columna de identidad. Pero ese cambio es muy muy difícil en grandes bases de datos.

Vaccano
fuente

Respuestas:

22

Su pregunta es, esencialmente:

¿Por qué ya no puedo hacer esta cosa arriesgada que nunca se me debería haber permitido hacer en primer lugar?

La respuesta a esa pregunta es en gran medida irrelevante (aunque puede ver algunos comentarios de Microsoft en estos elementos de Connect que solicitan esta funcionalidad: # 294193 y # 252226) Para completar, mi sinopsis es: la capacidad de eliminar la propiedad de identidad fue un efecto secundario no deseado de tener la capacidad de meterse con las tablas del sistema en primer lugar. Esto no estaba destinado a ser utilizado de las muchas maneras en que era, a menudo con muy malas consecuencias, y por lo tanto fue eliminado. Era un hack de tabla de sistema no documentado, no soportado. La capacidad de cambiar los datos en las tablas del sistema no se eliminó porque Microsoft ya no quería que salieras de una columna que era una columna de identidad, sino que se eliminó porque mudar las tablas del sistema es extremadamente riesgoso. La eliminación de la propiedad IDENTITY en sí misma no fue una eliminación de características específicamente dirigida, y nunca hubiera confiado completamente en este enfoque, incluso en los tiempos antiguos cuando era posible.

Dicho esto, ¿qué tal si respondemos esta pregunta en su lugar?

¿Cómo elimino la propiedad IDENTITY de una columna con un tiempo de inactividad mínimo o nulo?

Esto puede hacerlo fácilmente, utilizando ALTER TABLE ... SWITCHuna técnica que estoy seguro aprendí por primera vez de nuestro propio Paul White en las soluciones para Connect # 252226 . Ejemplo rápido, dada esta tabla simple:

CREATE TABLE dbo.Original
(
  ID INT IDENTITY(1,1) PRIMARY KEY,
  name SYSNAME
);
GO

INSERT dbo.Original(name) VALUES(N'foo'),(N'bar');
GO

SELECT * FROM dbo.Original;
GO

Resultados:

ID  name
--  ----
1   foo
2   bar

Ahora, creemos una tabla de sombra y cambiemos a ella, luego deje caer la tabla anterior, cambie el nombre de la nueva y luego reanude la actividad normal:

CREATE TABLE dbo.New
(
  ID INT PRIMARY KEY,
  name SYSNAME
);
GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
  ALTER TABLE dbo.Original SWITCH TO dbo.New;
  DROP TABLE dbo.Original;
  EXEC sys.sp_rename N'dbo.New', N'Original', 'OBJECT';
COMMIT TRANSACTION;
GO

INSERT dbo.Original(ID,name) VALUES(3,N'splunge');
UPDATE dbo.Original SET ID = 6 WHERE ID = 1;
GO

SELECT * FROM dbo.Original;
GO

Resultados:

ID  name
--  -------
2   bar
3   splunge
6   foo

Ahora limpia:

DROP TABLE dbo.Original;

Esta es una operación de metadatos solamente, sin movimiento de datos, y solo bloqueará a otros usuarios mientras se actualizan los metadatos. Pero, es cierto, es un ejemplo muy simplista. Si tiene claves foráneas o está utilizando otras funciones como la replicación, la captura de cambio de datos, el seguimiento de cambios, etc., es posible que deba desactivar o eliminar algunas de ellas antes de realizar este cambio (no he probado todas las combinaciones). Para claves foráneas específicamente, vea este consejo que muestra cómo generar scripts para descartar y volver a crear todas las restricciones de claves foráneas (o seleccionadas).

Además, deberá actualizar el código de su aplicación para no esperar que SQL Server llene esta columna, y verifique cualquier instrucción de inserción o selección que pueda depender del orden de las columnas o las columnas que necesitan especificar. En general, elegiría toda su base de código para cualquier mención de esta tabla.

También vea este script de Itzik Ben-Gan (fuente: este artículo antiguo ) para otra forma de manejar esto, pero hay un movimiento de datos involucrado aquí, por lo que no cumple con el requisito de "tiempo de inactividad mínimo o mínimo".

Aaron Bertrand
fuente
3
Me gustaría animar a cualquiera que venga a votar los dos elementos de conexión. ¿Qué tan difícil puede ser implementar una función ALTERAR COLUMNA que active o desactive la identidad booleana? Doloroso de evitar.
usr
Tengo que admitir que, por alguna razón, pensé que ..SWITCH..solo funcionaba para tablas que tenían al menos una partición definida.
RBarryYoung
Solo quiero agregar que SWITCHno requiere Enterprise Edition, aunque la partición de tablas sí.
Dan Guzman