529 votos

¿Cuál es la mejor manera de obtener la identidad de la fila insertada?

¿Cuál es la mejor manera de obtener la identidad de la fila insertada?

Sé de @@IDENTITY y IDENT_CURRENT y SCOPE_IDENTITY pero no entienden los pros y los contras de cada uno.

¿Puede alguien explicar las diferencias y cuándo debo utilizar cada una?

680voto

bdukes Puntos 54833
  • @@IDENTITY devuelve el último valor de identidad generado para cualquier tabla en la sesión actual, en todos los ámbitos. Hay que tener cuidado aquí ya que es a través de los ámbitos. Usted podría obtener un valor de un disparador, en lugar de su declaración actual.
  • SCOPE_IDENTITY devuelve el último valor de identidad generado para cualquier tabla en la sesión actual y el ámbito actual. Por lo general, lo que se desea es utilizar .
  • IDENT_CURRENT devuelve el último valor de identidad generado para una tabla específica en cualquier sesión y cualquier ámbito. Esto le permite especificar de qué tabla quiere el valor, en caso de que las dos anteriores no sean exactamente lo que necesita ( muy raro ). Además, como @ Guy Starbuck mencionó: "Podrías usar esto si quieres obtener el valor actual de IDENTIDAD de una tabla en la que no has insertado ningún registro".
  • El OUTPUT cláusula de la INSERT le permitirá acceder a cada fila que se haya insertado a través de esa sentencia. Dado que el ámbito de aplicación es la sentencia específica, es más sencillo que las otras funciones anteriores. Sin embargo, es un poco más verboso (tendrá que insertar en una variable de tabla/tabla temporal y luego consultarla) y da resultados incluso en un escenario de error en el que la sentencia se revierte. Dicho esto, si su consulta utiliza un plan de ejecución paralelo, este es el único método garantizado para obtener la identidad (sin desactivar el paralelismo). Sin embargo, se ejecuta antes de y no pueden utilizarse para devolver valores generados por el activador.

82voto

Orry Puntos 659

Creo que el método más seguro y preciso para recuperar el id insertado sería utilizar la cláusula de salida.

por ejemplo (tomado de lo siguiente MSDN artículo)

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate 
FROM Production.ScrapReason;
GO

56voto

Orion Edwards Puntos 54939

Digo lo mismo que los demás, así que todos están en lo cierto, sólo intento dejarlo más claro.

@@IDENTITY devuelve el id de lo último que fue insertado por la conexión de su cliente a la base de datos.
La mayoría de las veces esto funciona bien, pero a veces un disparador va a insertar una nueva fila que no conoces, y obtendrás el ID de esta nueva fila, en lugar del que quieres

SCOPE_IDENTITY() resuelve este problema. Devuelve el id de lo último que has insertado en el código SQL que enviaste a la base de datos. Si los desencadenantes van y crean filas adicionales, no harán que se devuelva el valor incorrecto. Hurra

IDENT_CURRENT devuelve el último ID que fue insertado por alguien. Si alguna otra aplicación inserta otra fila en un momento imprevisto, obtendrá el ID de esa fila en lugar del suyo.

Si quieres ir a lo seguro, utiliza siempre SCOPE_IDENTITY() . Si te quedas con @@IDENTITY y alguien decide añadir un disparador más tarde, todo su código se romperá.

23voto

Ian Kemp Puntos 6408

La mejor manera (léase: la más segura) de obtener la identidad de una fila recién insertada es utilizando la función output cláusula. No se garantiza que cualquier otro método devuelva el ID correcto cuando se utiliza el paralelismo - incluso si no se utiliza el paralelismo ahora Si se trata de un entorno paralelo (por ejemplo, un clúster de Sql Server), escribir su SQL de esta manera le asegurará que no tenga que cambiarlo.

create table TableWithIdentity
           ( IdentityColumnName int identity(1, 1) not null primary key,
             ... )

-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )

insert TableWithIdentity
     ( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
     ( ... )

select @IdentityValue = (select ID from @IdentityOutput)

5voto

erikkallen Puntos 16601

SIEMPRE usar scope_identity(), NUNCA hay necesidad de nada más.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X