none
Como mantener orden de campo Identity luego de eliminar un dato RRS feed

  • Pregunta

  • Buenas tardes,

    Yo tengo una estructura de tabla:

    Id_ usuario int identity(1,1) not null,

    Usuario varchar(50)not null

    Bien los datos de esa tabla se agregan directamente de C#, el caso es el siguien si elimina un usuario ejemplo:

    Supongamos que tengo  estos datos

    Id_usuario         Usuario

    1                      samuel

    2                      manuel

    si elimino a manuel el siguien datos que yo agregue se generara con el Id_usuario 3 cuando en realidad solo tendria 2 datos, igual que si eliminara a samuel el siguiente en generarse seria Id_usuario 3 y no hubiera un Id_usuario 1 quisiera saber como mantengo ese orden? no se si me di a entender


    samuel

    sábado, 8 de diciembre de 2018 19:37

Respuestas

  • Bien, si lo que quieres es que no solo se conserve la secuencia contigua si borras el último (para lo cual bastaría el MAX) sino también si se borra uno intermedio, entonces las cosas son mucho más delicadas. El problema es que tienes que "mover hacia abajo" TODOS los registros que haya por encima del borrado. Por ejemplo, si tienes un millón de registros y borras el número 3 entonces hay que renumerar los 999996 registros posteriores, cambiándoles el número a todos ellos, lo cual será costosísimo.

    Si a pesar de todo quieres hacerlo, entonces y dado que ya estás usando procedimientos almacenados para grabar, yo te recomendaría meter esa lógica en el procedimiento almacenado que haga el borrado. Esto es mucho mejor que usar un trigger. Básicamente el código que meterías en el procedimiento que borra sería algo así como esto:

    delete from Usuario where Id_Usuario=@IdABorrar;
    update Usuario Set Id=Usuario=Id_Usuario-1 where Id_Usuario>@IdABorrar;

    Dicho eso, y antes de ponerse a hacerlo, primero hay que cuestionarse por qué es necesario. Normalmente el campo ID se usa como identificador único para reconocer el correspondiente registro, y el identificador único se usa para relacionar esa tabla con otras tablas que usan ese mismo campo para "conectar" cierta otra información con el usuario. Pero si el ID cambia cuando borras un usuario, entonces se fastidian todas las relaciones, por lo que hay que concluir que no estás usando el ID para su uso natural como identificador del registro. Entonces hay que preguntarse para qué lo quieres y qué estás haciendo con ese dato para que se requiera que sea consecutivo, porque posiblemente el objetivo final se pueda lograr de alguna otra manera más eficiente que renumerando registros sobre la tabla.

    • Marcado como respuesta Samuel Ignacio domingo, 9 de diciembre de 2018 22:00
    domingo, 9 de diciembre de 2018 19:29

Todas las respuestas

  • El IDENTITY no sirve para lo que quieres lograr. Solo sirve para generar una secuencia de números creciente, pero no sirve para que la secuencia no tenga "agujeros". De hecho, hay muchos más casos en los que te puede salir uno de esos huecos, por ejemplo, si haces un rollback de una transacción o si se produce un error al grabar. Y a veces te queda un salto de 1000 unidades, por ejemplo, si reinicias el servidor cuando tenía algo pendiente sobre el identity.

    Así que si necesitas que tus registros sean perfectamente consecutivos, tienes que prescindir del identity y usar un campo numérico vulgar y corriente. Y a ese campo le asignas el valor desde código cliente (por ejemplo, haciendo un "select max" y sumándole 1) o incluso desde un Trigger si tu conjunto de aplicaciones así lo requiere.

    • Propuesto como respuesta Sergio Parra domingo, 9 de diciembre de 2018 12:46
    domingo, 9 de diciembre de 2018 9:53
  • Buenas tardes, Bien entiendo tu planteamiento pero segun veo con el "Select max" +1 solo conseguiria que el orden no se rompa ya que siempre traera el ultimo ID que esta en la tabla y le sumara uno(perfecto hasta ahi), pero no veo una forma de que si borro un usuario los ID se organicen nueva vez como explique que si tengo ID 1 Y ID 2 y borro el ID 1 quisiera que el ID 2 tome ese lugar y se convierta en ID 1 para que con el metodo que indicaste el siguien ID sea el ID 2 y no se rompa el orden, no se si me doy a entender?. Realmente hermano soy un poco nuevo en esto y no se utilizar Triggers, si te sirve de referencia trabajo los datos con procedimiento almacenados para Insertar, Eliminar, Actualizar y Consultar datos por si acaso me daras un codigo de referencia.

    samuel

    domingo, 9 de diciembre de 2018 15:38
  • Bien, si lo que quieres es que no solo se conserve la secuencia contigua si borras el último (para lo cual bastaría el MAX) sino también si se borra uno intermedio, entonces las cosas son mucho más delicadas. El problema es que tienes que "mover hacia abajo" TODOS los registros que haya por encima del borrado. Por ejemplo, si tienes un millón de registros y borras el número 3 entonces hay que renumerar los 999996 registros posteriores, cambiándoles el número a todos ellos, lo cual será costosísimo.

    Si a pesar de todo quieres hacerlo, entonces y dado que ya estás usando procedimientos almacenados para grabar, yo te recomendaría meter esa lógica en el procedimiento almacenado que haga el borrado. Esto es mucho mejor que usar un trigger. Básicamente el código que meterías en el procedimiento que borra sería algo así como esto:

    delete from Usuario where Id_Usuario=@IdABorrar;
    update Usuario Set Id=Usuario=Id_Usuario-1 where Id_Usuario>@IdABorrar;

    Dicho eso, y antes de ponerse a hacerlo, primero hay que cuestionarse por qué es necesario. Normalmente el campo ID se usa como identificador único para reconocer el correspondiente registro, y el identificador único se usa para relacionar esa tabla con otras tablas que usan ese mismo campo para "conectar" cierta otra información con el usuario. Pero si el ID cambia cuando borras un usuario, entonces se fastidian todas las relaciones, por lo que hay que concluir que no estás usando el ID para su uso natural como identificador del registro. Entonces hay que preguntarse para qué lo quieres y qué estás haciendo con ese dato para que se requiera que sea consecutivo, porque posiblemente el objetivo final se pueda lograr de alguna otra manera más eficiente que renumerando registros sobre la tabla.

    • Marcado como respuesta Samuel Ignacio domingo, 9 de diciembre de 2018 22:00
    domingo, 9 de diciembre de 2018 19:29
  • Bien, gracias. ahora que me explicas ese caso de las relaciones lo tendre en cuenta.

    samuel

    domingo, 9 de diciembre de 2018 22:00
  • Siempre nos hemos "peleado" para solucionar lo que comenta y en lo personal, llevar NÚMEROS SECUENCIALES en una tabla que sera afectada mediante DELETE, pues no hay solución. Lo único que EN LO PERSONAL he hecho para "solucionar" este tipo de cuestiones, es borrado lógico, un campo tipo booleano donde los 1 son registros activos y los 0 son registros borrados, asi, nunca se pierde la secuencia. Desconozco si con esto, dará solución satisfactoria a su planteamiento.


    IIslas Master Consultant SQL Server

    lunes, 10 de diciembre de 2018 19:50