Pregunta ¿La mejor forma de obtener la identidad de la fila insertada?


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

Se acerca de @@IDENTITY y IDENT_CURRENT y SCOPE_IDENTITY pero no entiendo los pros y los contras asociados a cada uno.

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


889
2017-09-03 21:32


origen


Respuestas:


  • @@IDENTITY devuelve el último valor de identidad generado para cualquier tabla en la sesión actual, en todos los ámbitos. Debes tener cuidado aquí, ya que está al otro lado de los ámbitos. Podría obtener un valor de un desencadenador, 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 alcance actual. Generalmente lo que quieres usar.

  • IDENT_CURRENT('tableName') 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 los dos anteriores no sean exactamente lo que necesita (muy raro) Tambien como @Guy Starbuck mencionado, "Podría usar esto si quiere obtener el valor de IDENTIDAD actual para una tabla en la que no ha insertado un registro".

  • los OUTPUT cláusula del INSERT declaración le permitirá acceder a cada fila que se insertó a través de esa declaración. Dado que tiene un alcance para la declaración específica, es más sencillo que las otras funciones anteriores. Sin embargo, es un poco más detallado (Necesitará insertar en una tabla variable / tabla temporal y luego consultar eso) y da resultados incluso en un escenario de error donde la declaración se revierte. Dicho esto, si su consulta usa un plan de ejecución paralelo, esta es la único método garantizado para obtener la identidad (excepto desactivar el paralelismo). Sin embargo, se ejecuta antes de desencadena y no puede utilizarse para devolver los valores generados por el activador.


1171
2017-09-03 21:38



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

por ejemplo (tomado de la 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

150
2018-05-20 14:43



Estoy diciendo lo mismo que los otros chicos, así que todos están en lo cierto, solo estoy tratando de dejarlo más claro.

@@IDENTITY devuelve el id. de lo último que insertó la conexión de su cliente a la base de datos.
La mayoría de las veces esto funciona bien, pero a veces se activa un disparador e inserta una nueva fila que no conoces, y obtendrás el ID de esta nueva fila, en lugar de la que deseas

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

IDENT_CURRENT devuelve la última identificación que fue insertada por cualquier persona. Si sucede que alguna otra aplicación inserta otra fila en un momento incierto, obtendrá la ID de esa fila en lugar de la suya.

Si quieres ir a lo seguro, siempre usa SCOPE_IDENTITY(). Si te quedas con @@IDENTITYy alguien decide agregar un disparador más adelante, todo su código se romperá.


94
2017-09-03 21:44



La mejor forma (más segura) de obtener la identidad de una fila recién insertada es usar el output cláusula:

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)

52
2018-04-29 07:22



Añadir

SELECT CAST(scope_identity() AS int);

al final de su instrucción Insert sql, luego

NewId = command.ExecuteScalar()

lo recuperará


20
2018-03-30 18:25



MSDN

@@ IDENTIDAD, SCOPE_IDENTITY e IDENT_CURRENT son funciones similares en que devuelven el último valor insertado en la columna IDENTIDAD de una tabla.

@@ IDENTITY y SCOPE_IDENTITY devolverán el último valor de identidad generado en cualquier tabla en la sesión actual. Sin embargo, SCOPE_IDENTITY devuelve el valor solo dentro del alcance actual; @@ IDENTIDAD no está limitado a un alcance específico.

IDENT_CURRENT no está limitado por el alcance y la sesión; está limitado a una tabla especificada. IDENT_CURRENT devuelve el valor de identidad generado para una tabla específica en cualquier sesión y cualquier ámbito. Para obtener más información, vea IDENT_CURRENT.

  • IDENT_CURRENT es una función que toma una tabla como argumento.
  • @@IDENTIDAD puede devolver resultados confusos cuando tienes un disparador sobre la mesa
  • SCOPE_IDENTITY es tu héroe la mayor parte del tiempo.

12
2017-09-03 21:37



@@IDENTIDAD es la última identidad insertada utilizando la Conexión SQL actual. Este es un buen valor para devolver desde un procedimiento insert insertado, donde solo necesita la identidad insertada para su nuevo registro, y no importa si se agregaron más filas después.

SCOPE_IDENTITY es la última identidad insertada utilizando la Conexión SQL actual, y en el ámbito actual, es decir, si hubo una segunda IDENTIDAD insertada en función de un desencadenante después de su inserción, no se reflejaría en SCOPE_IDENTITY, solo la inserción que realizó. Francamente, nunca tuve una razón para usar esto.

IDENT_CURRENT (nombre de tabla) es la última identidad insertada independientemente de la conexión o el alcance. Puede usar esto si desea obtener el valor de IDENTIDAD actual para una tabla en la que no ha insertado un registro.


11
2017-09-03 21:42



Cuando utiliza Entity Framework, internamente usa el OUTPUT técnica para devolver el valor de ID recién insertado

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');

SELECT t.[TurboEncabulatorID ]
FROM @generated_keys AS g 
   JOIN dbo.TurboEncabulators AS t 
   ON g.Id = t.TurboEncabulatorID 
WHERE @@ROWCOUNT > 0

Los resultados de salida se almacenan en una variable de tabla temporal, se unen a la tabla y devuelven el valor de la fila fuera de la tabla.

Nota: No tengo idea de por qué EF uniría internamente la tabla efímera a la tabla real (bajo qué circunstancias los dos no coincidirían).

Pero eso es lo que hace EF.

Esta tecnica (OUTPUT) solo está disponible en SQL Server 2008 o posterior.


10
2017-11-04 15:05



SIEMPRE use scope_identity (), NUNCA hay necesidad de otra cosa.


7
2017-10-09 20:35



No puedo hablar con otras versiones de SQL Server, pero en 2012, la salida funciona directamente bien. No necesita molestarse con una tabla temporal.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

Por cierto, esta técnica también funciona al insertar múltiples filas.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

Salida

ID
2
3
4

2
2018-06-06 16:58



Después de su declaración de inserción, debe agregar esto. Y asegúrese de que el nombre de la tabla donde se están insertando los datos. Obtendrá la fila actual, no en la fila afectada ahora por su declaración de inserción.

IDENT_CURRENT('tableName')

0
2017-12-31 06:04