Java - Solución para actualizar en serie los Id de una Tabla -Resuelto

 
Vista:

Solución para actualizar en serie los Id de una Tabla -Resuelto

Publicado por YYanes (144 intervenciones) el 21/03/2017 17:45:27
Hola:

Muchas veces nos matamos diseñando un algoritmo muy complejo en Java, cuando la solución podría ser fácil si la ejecutamos en la propia base de datos. La solución que ofreceré a continuación tiene que ver ante todo con Postgres, pero dado a su estrecha relación con Java (entiéndase el frecuente uso de ambos juntos) la mostraré aquí por si alguien la necesita algún día.

He entrado en varios foros y espacios y me he encontrado la siguiente pregunta: ¿cómo actualizar en serie un atributo clave principal de una tabla, para así eliminar espacios vacíos y saltos de número?

Si declaramos un atributo como Llave Primaria en una tabla, y lo definimos de tipo "Sequence", "Identity" o "Serial" (como quieran llamarlo), estaremos creando un atributo cuyo valor se generará automáticamente en el gestor. Por ejemplo:

MiTablaX // Id es llave primaria de tipo "identity" o "serial"
-Id --- Atrib1(String) --- Atr2(int)
- 1 --- 'abc' -------------- 111
- 2 --- 'bcd' -------------- 222
- 3 --- 'ekg' -------------- 333
- 4 --- 'hkk' -------------- 444
- 5 --- 'kmi' -------------- 555

Insert INTO MiTabla Values('xyz', 999); //No es necesario pasarle el valor del Id, ya que se autoincrementa automáticamente, quedando:

MiTablaX
- 1 --- 'abc' -------------- 111
- 2 --- 'bcd' -------------- 222
- 3 --- 'ekg' -------------- 333
- 4 --- 'hkk' -------------- 444
- 5 --- 'kmi' -------------- 555
- 6 --- 'xyz' -------------- 999

Pero al eliminar registros de la tabla, quedan espacios vacíos y saltos entre uno y otro. Por ejemplo:

MiTablaX
- 2 --- 'bcd' -------------- 222
- 3 --- 'ekg' -------------- 333
- 6 --- 'xyz' -------------- 999
//-- Véase que el primer Id no comienza en 1, y luego faltan números entre un Id y otro

//----- LA SOLUCIÓN: -----------

with MiTabla_numerada
as(
select id, row_number() over(order by Id) as rw from MiTabla
)
update MiTabla SET Id = (Select rw from MiTabla_numerada WHERE MiTabla.Id = MiTabla_numerada.Id);

SELECT setval('public.mitabla_id_seq', (Select MAX(id)+1 from MiTabla), true);
//-----------------------

Explicación:
- La función "row_number() over(order by Id) as rw from MiTabla" me devuelve la secuencia numérica de todos los Id de la tabla independientemente de su valor, pero el valor devuelto solo es mostrado en tiempo de ejecusión, por eso...
- necesitamos ponerlo en una tabla temporal mediante el uso de "with MiTabla_numerada as(...)" junto con los valores Id de la tabla original, luego...
- Puedo proceder al UPDATE ya que tengo un dato con el que comparar cada Id, más el valor secuencial que quiero asignarle. Finalmente...
- Para reestablecer la posición (valor actual) de la secuencia, y que el siguiente Insert genere el Id correcto, ejecutamos la función "setval(identity, posición, true)", y la posición la obtenemos preguntando por el mayor Id de la tabla, al cual hay que sumarle 1.

Y ya está!!! La explicación puede parecer larga, pero la solución es bastante simple. Preferiblemente le recomiendo crear un Procedimiento Almacenado en su base de datos, y luego llamarlo desde su aplicación en Java, aunque por supuesto, si quiere utilizarlo directamente... nadie se lo prohibe ;)

Un GigaSaludo!!!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder