none
¿Es posible crear un trigger o proceso que incremente un contador para todas la tablas de una base de datos? RRS feed

  • Pregunta

  • Actualmente he visto que el identity de sql server se salta los autoincrementables, por lo que quisiera saber si es posible hacer el incremento de ese campo con un proceso aparte, normalmente uso identity como llaves primarias.

    También quisiera saber si es recomendable hacerlo de esa forma o mejor busco como solucionar el problema de SQL (que por cierto no soy el administrador del servidor y por cuestiones de permisos no creo ser la persona indicada para corregir el problema, puedo solicitar que lo verifiquen pero en lo que espero me estaría atrasando con mi desarrollo).



    BCJ

    jueves, 1 de marzo de 2018 15:32

Respuestas

  • Primero: lo del "proceso aparte": Puedes crear un trigger de tipo "after insert" en la tabla, que haga un "select MAX(...)" y lo use para generar el campo incremental. Sera mas lento que el identity, pero te permite garantizar que los valores son consecutivos, siempre que lo ejecutes con el suficiente nivel de aislamiento en las transacciones (creo que read commited seria suficiente). Obviamente, si usas el trigger tienes que quitar el Identity, no pueden funcionar las dos cosas a la vez sobre el mismo campo.

    En cuanto a lo de solucionar el problema en el SQL Server: Si el problema que tienes es que de vez en cuando, sobre todo al reiniciar el servidor, se te salta 1000 posiciones en el Identity, entonces si no me equivoco hay un parche que lo arregla. Pero si el problema es que cuando inicias una transaccion, consumes un valor del identity, y haces un rollback, entonces se "pierde" ese valor (el rollback no lo devuelve), entonces no tiene remedio. Si te enfrentas con este problema, tendras que cambiarte a la opcion de usar el MAX, bien sea desde un trigger o desde codigo cliente.


    Observacion: mencionas que el Identity lo usas como llave primaria. Para este proposito, no hay ningun problema en que se "salte" valores. Eso es perfectamente válido para una clave primaria. El problema solo surge cuando se pretende usar el Identity para generar un valor que no deba tener saltos, como por ejemplo un numero de factura. Para este ultimo fin es para lo que no sirve el identity, y hay que usar el MAX. Para las claves primarias no importa que haya saltos (y en caso de que si que importe entonces quiere decir que se ha hecho un mal diseño, es decir, se esta usando el Identity que es un mecanismo para claves subrogadas con el fin de generar una clave de negocio en lugar de una clave subrogada).
    jueves, 1 de marzo de 2018 15:41

Todas las respuestas

  • Primero: lo del "proceso aparte": Puedes crear un trigger de tipo "after insert" en la tabla, que haga un "select MAX(...)" y lo use para generar el campo incremental. Sera mas lento que el identity, pero te permite garantizar que los valores son consecutivos, siempre que lo ejecutes con el suficiente nivel de aislamiento en las transacciones (creo que read commited seria suficiente). Obviamente, si usas el trigger tienes que quitar el Identity, no pueden funcionar las dos cosas a la vez sobre el mismo campo.

    En cuanto a lo de solucionar el problema en el SQL Server: Si el problema que tienes es que de vez en cuando, sobre todo al reiniciar el servidor, se te salta 1000 posiciones en el Identity, entonces si no me equivoco hay un parche que lo arregla. Pero si el problema es que cuando inicias una transaccion, consumes un valor del identity, y haces un rollback, entonces se "pierde" ese valor (el rollback no lo devuelve), entonces no tiene remedio. Si te enfrentas con este problema, tendras que cambiarte a la opcion de usar el MAX, bien sea desde un trigger o desde codigo cliente.


    Observacion: mencionas que el Identity lo usas como llave primaria. Para este proposito, no hay ningun problema en que se "salte" valores. Eso es perfectamente válido para una clave primaria. El problema solo surge cuando se pretende usar el Identity para generar un valor que no deba tener saltos, como por ejemplo un numero de factura. Para este ultimo fin es para lo que no sirve el identity, y hay que usar el MAX. Para las claves primarias no importa que haya saltos (y en caso de que si que importe entonces quiere decir que se ha hecho un mal diseño, es decir, se esta usando el Identity que es un mecanismo para claves subrogadas con el fin de generar una clave de negocio en lugar de una clave subrogada).
    jueves, 1 de marzo de 2018 15:41
  • Gracias por tu respuesta Alberto, pues en realidad el hecho que se salte el identity no debe afectar mi diseño actual, supongo que crearé triggers para las tablas específicas que tendrán muchos datos que son los que me preocupan para no llegar a topar las claves algún día.

    Tomaré en cuenta las recomendaciones.

    Saludos.


    BCJ

    jueves, 1 de marzo de 2018 16:02
  • [...] son los que me preocupan para no llegar a topar las claves algún día.

    Si tu preocupación es esa, probablemente una solución más sencilla sea cambiar el INT por BIGINT.
    jueves, 1 de marzo de 2018 16:54