lunes, 9 de diciembre de 2013

IDENTITY vs SCOPE_IDENTITY()


En esta entrada exploraremos la diferencia entre estas dos funciones del sistema que mucha gente utiliza y que es sumamente importante conocer el valor que están devolviendo.

Comenzaremos creando dos tablas, en una agregaremos valores y la otra servirá para llevar un historial muy sencillo de movimientos:
CREATE TABLE TestIdentity( Id INT IDENTITY(1, 1), Value VARCHAR(10) NOT NULL ) GO CREATE TABLE TestIdentityLog( Id INT IDENTITY(1, 1), Task VARCHAR(10), Value VARCHAR(10) )

En la tabla TestIdentity iremos guardando valores de prueba y la tabla TestIdentityLog estará guardando el historial de movimientos que se han llevado a cabo sobre la tabla TestIdentity. Debemos notar que en las dos tablas tenemos una columna IDENTITY.

Ahora vamos a crear dos triggers, uno para el INSERT y otro para el DELETE:
CREATE TRIGGER TestIdentity_Insert ON TestIdentity FOR INSERT AS BEGIN INSERT INTO TestIdentityLog (Task, Value) SELECT 'INSERT', Value FROM INSERTED END GO CREATE TRIGGER TestIdentity_Delete ON TestIdentity FOR DELETE AS BEGIN INSERT INTO TestIdentityLog (Task, Value) SELECT 'DELETE', Value FROM DELETED END

Ambos guardan el movimiento en la tabla de historial, sólo que el primero es para INSERT y el segundo para DELETE

Vamos a crear un procedimiento almacenado para agregar un valor a TestIdentity, de paso mostraremos el resultado de la ejecución de los dos valores que nos interesan: @@IDENTITY y SCOPE_IDENTITY():
CREATE PROC pAddValue( @Value VARCHAR(10) ) AS BEGIN INSERT INTO TestIdentity (Value) VALUES (@Value) PRINT '@@IDENTITY: ' + CAST(@@IDENTITY AS VARCHAR) PRINT 'SCOPE_IDENTITY(): ' + CAST(SCOPE_IDENTITY() AS VARCHAR) END

Ahora vamos a crear un procedimiento almacenado que nos permita eliminar un elemento de la tabla TestIdentity:
CREATE PROC pDeleteValue( @Id INT ) AS BEGIN DELETE TestIdentity WHERE Id = @Id END

Habitualmente se piensa que podemos utilizar cualquiera de los dos sin problema, pero al ejecutar el siguiente código veremos que ambas nos mostrarán números diferentes en la tercera ejecución:
SET NOCOUNT ON GO EXEC pAddValue 'Valor 1' GO EXEC pDeleteValue 1 GO EXEC pAddValue 'Valor 1'

El primer EXEC mostrará que @@IDENTITY devuelve 1 y SCOPE_IDENTITY() devuelve 1, pero veremos que el tercer EXEC mostrará que @@IDENTITY devuelve 3 y SCOPE_IDENTITY() devuelve 2.

Esto se debe a que @@IDENTITY devuelve el último valor obtenido a través de una columna IDENTITY, este valor pertence a la columna Id de la tabla TestIdentityLog, los trigger que se están disparando ante el INSERT o DELETE son los que están realizando esa inserción y por lo tanto el último valor asignado es el de la tabla TestIdentityLog.

La función SCOPE_IDENTITY() devuelve el último valor asignado por IDENTITY en el entorno actual de ejecución, para nuestro procedimiento pAddValue el único IDENTITY que tiene a su alcance es el que está en la columna Id de la tabla TestIdentity, es por ello que devuelve el valor 2.

Como podrás notar, es importante conocer la diferencia entre las dos opciones que tenemos, dependerá del objetivo del procedimiento o de la operación cuál te resulte adecuado a tus necesidades; generalmente utilizarás SCOPE_IDENTITY()

Espero esta entrada te haya resultado útil, nos vemos la siguiente.

No hay comentarios.:

Publicar un comentario