Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=9553ea1e-fdea-47c1-a81f-d653019333e0

SQL Server: cuáles son las diferencias entre @@identity y Scope_identity


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!

Fecha de publicación:
José Manuel Alarcón Fundador de campusMVP, es ingeniero industrial y especialista en consultoría de empresa. Ha escrito diversos libros, habiendo publicado hasta la fecha cientos de artículos sobre informática e ingeniería en publicaciones especializadas. Microsoft lo ha reconocido como MVP (Most Valuable Professional) en desarrollo web desde el año 2004 hasta la actualidad. Puedes seguirlo en Twitter en @jm_alarcon o leer sus blog técnico o personal. Ver todos los posts de José Manuel Alarcón
Archivado en: Acceso a Datos

¿Te ha gustado este post?
Pues espera a ver nuestro boletín mensual...

Suscríbete a la newsletter

La mejor formación online para desarrolladores como tú

Comentarios (2) -

Rafa Vidal
Rafa Vidal

Buenas... Todos los posibles problemas al usar con PK los autonuméricos, se solventarían usando como PK un campo uniqueidentifier con el valor predeterminado newid().

Un saludo.

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola Rafa:

Bueno, solucionan algunos problemas pero crean otros. De hecho si los generas en la base de datos necesitas una forma para obtenerlos cuando insertes algo y sería el mismo problema del que se habla en este artículo. Claro que los puedes pasar desde cliente, pero eso también tiene sus pequeños problemas.

Te dejo un enlace de la propia Microsoft que lo explica mejor de lo que lo podría explicar yo:

- blogs.msdn.microsoft.com/.../

Saludos!

Responder

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.