¿Cuál es la diferencia entre Scope_Identity (), Identity (), @@ Identity e Ident_Current ()?

192

Yo sé Scope_Identity(), Identity(), @@Identity, y Ident_Current()todas consigo el valor de la columna de identidad, pero me gustaría saber la diferencia.

Parte de la controversia que estoy teniendo es ¿qué quieren decir con alcance según se aplica a estas funciones anteriores?

También me encantaría un ejemplo simple de diferentes escenarios de uso de ellos?

Tebo
fuente
2
No olvide el error de ejecución paralela que existe en SQL Server para SCOPE_IDENTITY y @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas
@DaviddCeFreitas: tengo curiosidad por leer sobre el error, pero el enlace parece estar roto (o al menos, está arrojando un error ASP).
rory.ap
2
En realidad, lo encontré: support.microsoft.com/en-us/kb/2019779
rory.ap
La corrección se había publicado como se mencionó en ese antiguo artículo de KB
George Birbilis,

Respuestas:

396
  • La @@identityfunción devuelve la última identidad creada en la misma sesión.
  • La scope_identity()función devuelve la última identidad creada en la misma sesión y el mismo alcance.
  • El ident_current(name)devuelve el último identidad creada para una tabla específica o ver en cualquier sesión.
  • La identity()función no se usa para obtener una identidad, se usa para crear una identidad en una select...intoconsulta.

La sesión es la conexión de la base de datos. El alcance es la consulta actual o el procedimiento almacenado actual.

Una situación en la que scope_identity()las @@identityfunciones y difieren es si tiene un activador en la tabla. Si tiene una consulta que inserta un registro, haciendo que el activador inserte otro registro en algún lugar, la scope_identity()función devolverá la identidad creada por la consulta, mientras que la @@identityfunción devolverá la identidad creada por el activador.

Entonces, normalmente usarías la scope_identity()función.

Guffa
fuente
14
Elegí esto como respuesta, debido a la "Una situación en la que el alcance_identidad () y el @ @ identidad ..." párrafo. Aclaró las cosas más.
Tebo
1
Como David Freitas mencionó anteriormente, hay un error en la implementación de scope_identity, por lo que recomiendo usar un método alternativo, la cláusula OUTPUT. Vea mi respuesta a continuación.
Sebastian Meine
@Guffa - "La sesión es la conexión de la base de datos". ¿Se mantiene la sesión en todas las conexiones si está utilizando la agrupación de conexiones?
Dave Black el
1
Esta es una respuesta a seguir. En particular, trabajar con SQL y SQL Server puede ser extraño, y esto explica las cosas de una manera muy clara y simple, sin dejar de ser bastante informativo. No parece que algo se comunique entre dos especialistas en bases de datos, lo que hacen MUCHAS otras respuestas SE.
Panzercrisis
@DaveBlack de lo que leí: No, la sesión no se mantiene en el grupo, la sesión es única para su ejecución de script después de connect (). Al agrupar ... PHP para SQL Server utiliza la agrupación de conexiones ODBC. Cuando se utiliza una conexión del grupo, el estado de la conexión se restablece. Cerrar la conexión devuelve la conexión al grupo. (nota: ver comentarios para linux / mac) docs.microsoft.com/en-us/sql/connect/php/…
GDmac
42

Buena pregunta.

  • @@IDENTITY: devuelve el último valor de identidad generado en su conexión SQL (SPID). La mayoría de las veces será lo que desea, pero a veces no lo es (como cuando se dispara un disparador en respuesta a un INSERT, y el disparador ejecuta otra INSERTdeclaración).

  • SCOPE_IDENTITY(): devuelve el último valor de identidad generado en el ámbito actual (es decir, procedimiento almacenado, disparador, función, etc.).

  • IDENT_CURRENT(): devuelve el último valor de identidad para una tabla específica. No use esto para obtener el valor de identidad de un INSERT, está sujeto a condiciones de carrera (es decir, múltiples conexiones que insertan filas en la misma tabla).

  • IDENTITY(): se utiliza al declarar una columna en una tabla como columna de identidad.

Para obtener más información, consulte: http://msdn.microsoft.com/en-us/library/ms187342.aspx .

Para resumir: si está insertando filas y desea conocer el valor de la columna de identidad para la fila que acaba de insertar, utilice siempre SCOPE_IDENTITY().

Brannon
fuente
16

Si comprende la diferencia entre el alcance y la sesión, será muy fácil comprender estos métodos.

Una muy buena publicación de blog de Adam Anderson describe esta diferencia:

Sesión significa la conexión actual que está ejecutando el comando.

Alcance significa el contexto inmediato de un comando. Cada llamada a procedimiento almacenado se ejecuta en su propio alcance, y las llamadas anidadas se ejecutan en un alcance anidado dentro del alcance del procedimiento de llamada. Del mismo modo, un comando SQL ejecutado desde una aplicación o SSMS se ejecuta en su propio ámbito, y si ese comando dispara algún activador, cada activador se ejecuta dentro de su propio ámbito anidado.

Por lo tanto, las diferencias entre los tres métodos de recuperación de identidad son las siguientes:

@@identitydevuelve el último valor de identidad generado en esta sesión pero cualquier ámbito.

scope_identity()devuelve el último valor de identidad generado en esta sesión y este alcance.

ident_current()devuelve el último valor de identidad generado para una tabla en particular en cualquier sesión y cualquier ámbito.

Hemant Sakta
fuente
11

Alcance significa el contexto de código que realiza la INSERTdeclaración SCOPE_IDENTITY(), a diferencia del alcance global de @@IDENTITY.

CREATE TABLE Foo(
  ID INT IDENTITY(1,1),
  Dummy VARCHAR(100)
)

CREATE TABLE FooLog(
  ID INT IDENTITY(2,2),
  LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
  INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
  INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END

INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY 

Da resultados diferentes.

devio
fuente
6

Para aclarar el problema con @@Identity:

Por ejemplo, si inserta una tabla y esa tabla tiene activadores que realizan inserciones, @@Identitydevolverá la identificación de la inserción en el activador (ao log_idalgo), mientras scope_identity()que devolverá la identificación de la inserción en la tabla original.

Entonces, si no tiene ningún desencadenante scope_identity()y @@identitydevolverá el mismo valor. Si tiene desencadenantes, debe pensar qué valor le gustaría.

Jonas Lincoln
fuente
4

Scope Identity: Identidad del último registro agregado dentro del procedimiento almacenado que se está ejecutando.

@@Identity: Identidad del último registro agregado dentro del lote de consulta, o como resultado de la consulta, por ejemplo, un procedimiento que realiza una inserción, luego dispara un disparador que luego inserta un registro devolverá la identidad del registro insertado desde el disparador.

IdentCurrent: La última identidad asignada para la tabla.

Andrés
fuente
3

Aquí hay otra buena explicación del libro :

En cuanto a la diferencia entre SCOPE_IDENTITY y @@ IDENTITY, suponga que tiene un procedimiento almacenado P1 con tres declaraciones:
- Un INSERT que genera un nuevo valor de identidad
- Una llamada a un procedimiento almacenado P2 que también tiene una instrucción INSERT que genera un nuevo valor de identidad
: una declaración que consulta las funciones SCOPE_IDENTITY y @@ IDENTITY. La función SCOPE_IDENTITY devolverá el valor generado por P1 (misma sesión y alcance). La función @@ IDENTITY devolverá el valor generado por P2 (misma sesión independientemente del alcance).

Dmitriy Dokshin
fuente