SQL Server: cuáles son las diferencias entre @@identity y Scope_identity
José M. Alarcón 🌐
Posted on September 20, 2018
Foto de Kyle Glenn en Unsplash
Cuando insertamos un registro en una tabla de una base de datos, lo más habitual es que se genere automáticamente un nuevo identificador único para el nuevo registro, generalmente un autonumérico. Esto significa que empezamos en el 1 y para cada nuevo registro que añadimos se va aumentando de manera automática a 2, 3, 4... y así sucesivamente. Esto que parece una tontería, tiene muchas implicaciones ya que este identificador es el que vamos a utilizar luego para relacionar el nuevo registro con cualquier otra tabla de la base de datos que necesite utilizarlo. Por ejemplo, una factura y sus líneas de factura están relacionadas a partir del identificador de la cabecera. Cosas por el estilo...
El caso es que la generación de este autonumérico , que parece una tontería, es mucho más compleja de lo que parece ya que se debe tener en cuenta una cosa muy importante: la simultaneidad. Cuando tú haces pruebas en tu equipo de desarrollo, añadir nuevos registros es muy fácil: solo estás tú. Pero en un sistema real en el que pueden estar entrando miles de usuarios a la vez y añadiendo registros en las mismas tablas, el sistema debe asegurar que la secuencia se cumple sin dejar huecos y que no se producen bloqueos importantes.
Una manera ingenua de obtener el autonumérico de un registro que acabas de insertar sería simplemente obtener el máximo de esos números justo a continuación de hacer el INSERT
correspondiente. Pero en un sistema en producción no te funcionará con garantías salvo que provoques un bloqueo, ya que mucha gente puede estar introduciendo datos a la vez y entre que insertas el tuyo y lees el máximo puede haberse insertado otro. Es un problema peliagudo.
Cada sistema gestor de base de datos relacionales (SGBDR) que hay en el mercado aborda el problema con su propia filosofía. Ya os hemos explicado aquí cómo obtener el último autonumérico insertado en los más utilizados: Oracle , MySQL y SQL Server.
En el caso de SQL Server explicábamos que la forma de hacerlo era utilizando la instrucción SCOPE_IDENTITY()
. Puedes repasarlo en el enlace anterior. Sin embargo SQL Server ofrece al menos 3 formas de obtener el último ID insertado. Aunque puedan parecer iguales, no son equivalentes y conocer sus diferencias es muy importante:
-
@@Identity
: devuelve el último ID en la misma conexión. -
Scope_identity()
: la que recomendamos, devuelve el último ID creado en la misma conexión y el mismo contexto (de ahí su nombre). En este caso el contexto se refiere a la consulta o procedimiento almacenado actual. -
ident_current(nombre)
: devuelve el último ID de la tabla que le indiquemos (el que haya en ese momento)
En la mayor parte de los casos @@identity
y scope_identity()
se comportan igual, pero no siempre es así.
Por ejemplo, si tenemos un disparador (trigger) en nuestra tabla y lanzamos una consulta de inserción que genera un nuevo registro y por lo tanto un nuevo ID, si el trigger a su vez genera otro registro en otra tabla (y probablemente otro ID en ésta), en esta situación @@identity
nos devolverá el ID del registro que ha insertado el disparador , no el ID de la tabla que hemos actualizado (lo cual no es lo que queremos casi nunca), ya que te devuelve el último que se haya generado en esa conexión, tal y comentábamos en la lista anterior. Sin embargo, en este ejemplo, scope_identity()
nos devuelve el identificador que esperábamos (el de la inserción en nuestra tabla) ya que siempre devuelve el del contexto actual, que en este caso es nuestra consulta de inserción.
Este es el motivo de que normalmente se recomiende el uso de scope_identity()
.
¡Espero que te resulte útil!
Posted on September 20, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 20, 2018