Cambiar en SQLServer 2008 la columna clave de una tabla a una nueva del tipo integer que sea identidad usando OVER

Puede ser que en algun momento pueda ser necesario cambiar el tipo de columna clave para nuestra tabla/s por un mal diseño o un cambio posterior x que nos obliga a ello. Si lo hacemos y la nueva tiene que ser una columna del tipo entero, quizás identity, podemos hacerlo con algun criterio para que quede ordenado (pk=indice clusterizado=order by en disco por ese campo). En este ejemplo para hacerlo más completo, lo hacemos en dos tablas Maestro-Detalle donde los campos claves son de tipo nchar (CABECERAS.ID_CABECERA y LINEAS.ID_LINEA). Pasos a seguir...

  • Empezamos por elegir el tipo de columna y la añadimos a la tabla principal, CABECERAS. Seguimos con un update que parte de una join con una select sobre la misma tabla incluyendo la función ROW_NUMBER() para el contador de linea que nos servira como valor autoincremental (identity?). 
USE DBTEST; ALTER TABLE CABECERAS ADD PK_CABECERA int NULL; UPDATE CABECERAS SET PK_CABECERA = A.NUMERO_FILA FROM CABECERAS INNER JOIN (SELECT ROW_NUMBER() OVER (ORDER BY FECHA ASC) AS NUMERO_FILA FROM CABECERAS) A ON CABECERAS.ID_CABECERA = A.ID_CABECERA;
  • A coninuacións seguimos con el detalle, LINEAS, donde hacemos lo mismo que antes con su propia PK. Para mantener el mismo orden hacemos una join con la tabla CABECERAS y aprovechamos también para asignar también el valor de la nueva foreign key.
USE DBTEST; ALTER TABLE LINEAS ADD PK_LINEA int NULL; ALTER TABLE LINEAS ADD FK_CABECERA int NULL; UPDATE LINEAS SET PK_LINEA = A.NUMERO_FILA, FK_CABECERA = PK_CABECERA FROM LINEAS INNER JOIN (SELECT ROW_NUMBER() OVER (ORDER BY FECHA ASC) AS NUMERO_FILA, ID_LINEA, PK_CABECERA FROM LINEAS INNER JOIN CABECERAS ON CABECERAS.ID_CABECERA=LINEAS.ID_CABECERA) A ON LINEAS.ID_LINEA = A.ID_LINEA;

Ahora que ya tenemos los nuevos candidatos a campo clave, los marcaremos como NOT NULL, como campo clave y optaremos si es necesario por ponerlos como identity. También modificaremos la FOREIGN KEY o añadiremos una nueva. Una forma muy fácil de hacer lo anterior es hacerlo de forma visual, usando Management Studio, en la parte de Diagramas de Bases de datos (en el árbol del Explorador de objetos).

Por cierto, si finalmente hace falta que las nuevas claves sea identity deberemos recuperar antes el valor máximo del campo en las dos tablas para asignar el valor inicial de la identidad. Si queremos ser más puristas, debemos saber que desde SqlServer 2012 existen las secuencias y ya podríamos hacer lo mismo usándolas. Es interesante saber por una eventual migración de tipo de base de datos. A saber, Oracle también permite el uso de secuencias pero no existe equivalente a campos identity. MySql en cambio si tiene identity y es AUTO_INCREMENT.