sql - una - que es identity
¿La mejor manera de obtener la identidad de la fila insertada? (11)
Añadir
SELECT CAST(scope_identity() AS int);
hasta el final de su declaración Insertar SQL, entonces
NewId = command.ExecuteScalar()
lo recuperará.
¿Cuál es la mejor manera de obtener la IDENTITY
de la fila insertada?
Sé sobre @@IDENTITY
e IDENT_CURRENT
y SCOPE_IDENTITY
pero no entiendo los pros y los contras de cada uno.
¿Alguien puede explicar las diferencias y cuándo debo usar cada una?
Creo que el método más seguro y preciso para recuperar la identificación insertada sería usar la cláusula de salida.
por ejemplo (tomado del siguiente artículo de MSDN )
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
Cuando utiliza Entity Framework, utiliza internamente la técnica de OUTPUT
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 de nuevo a la tabla y devuelven el valor de la fila fuera de la tabla.
Nota: No tengo idea de por qué EF uniría la tabla efímera con la tabla real (en qué circunstancias no coincidirían las dos).
Pero eso es lo que hace EF.
Esta técnica ( OUTPUT
) solo está disponible en SQL Server 2008 o más reciente.
Después de su declaración de inserción debe agregar esto. Y asegúrese del nombre de la tabla donde se están insertando los datos. Obtendrá la fila actual en la fila afectada en este momento por su declaración de inserción.
IDENT_CURRENT(''tableName'')
Estoy diciendo lo mismo que los otros muchachos, así que todos están en lo cierto, solo trato de dejarlo más claro.
@@IDENTITY
devuelve el ID de lo último que se insertó con la conexión de su cliente a la base de datos.
La mayoría de las veces esto funciona bien, pero a veces un activador activará una nueva fila que no conoce, y obtendrá la identificación de esta nueva fila, en lugar de la que desea.
SCOPE_IDENTITY()
resuelve este problema. Devuelve el ID de lo último que insertó en el código SQL que envió a la base de datos. Si los activadores se activan y crean filas adicionales, no harán que se devuelva el valor incorrecto. ¡Hurra
IDENT_CURRENT
devuelve el último ID insertado por cualquier persona. Si alguna otra aplicación inserta otra fila en un momento no deseado, obtendrás la ID de esa fila en lugar de la tuya.
Si quieres jugar seguro, usa siempre SCOPE_IDENTITY()
. Si te quedas con @@IDENTITY
y alguien decide agregar un desencadenante más adelante, se romperá todo tu código.
La mejor manera (leer: la más segura) de obtener la identidad de una fila recién insertada es mediante el uso de la cláusula de output
:
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)
No puedo hablar con otras versiones de SQL Server, pero en 2012, la salida funciona directamente bien. No necesitas molestarte con una tabla temporal.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)
Por cierto, esta técnica también funciona cuando se insertan varias filas.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
(...),
(...),
(...)
Salida
ID
2
3
4
@@ IDENTITY, SCOPE_IDENTITY e IDENT_CURRENT son funciones similares, ya que devuelven el último valor insertado en la columna IDENTITY 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; @@ IDENTITY no se limita 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, consulte IDENT_CURRENT.
- IDENT_CURRENT es una función que toma una tabla como argumento.
- MSDN puede devolver un resultado confuso cuando tiene un disparador en la mesa
- SCOPE_IDENTITY es tu héroe la mayor parte del tiempo.
@@ IDENTITY es la última identidad insertada usando la conexión SQL actual. Este es un buen valor para regresar de un procedimiento almacenado de inserción, en el que solo necesita insertar la identidad para su nuevo registro, y no importa si se agregaron más filas después.
SCOPE_IDENTITY es la última identidad insertada usando la conexión SQL actual, y en el alcance actual, es decir, si se insertó una segunda IDENTIDAD basada en un disparador después de su inserción, no se reflejaría en SCOPE_IDENTITY, solo la inserción que realizó. . Francamente, nunca he tenido 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.
SIEMPRE use scope_identity (), NUNCA es necesario para nada más.
@@IDENTITY
devuelve el último valor de identidad generado para cualquier tabla en la sesión actual, en todos los ámbitos. Tienes que tener cuidado aquí , ya que es a través de ámbitos. Podría obtener un valor de un activador, 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 desea el valor, en caso de que las dos anteriores no sean exactamente lo que necesita ( muy raro ). Además, como mencionó @ Guy Starbuck , "Podría usar esto si desea obtener el valor de IDENTIDAD actual para una tabla en la que no ha insertado un registro".La cláusula
OUTPUT
de laINSERT
le permitirá acceder a cada fila que se insertó a través de esa declaración. Dado que está dentro del alcance de la declaración específica, es más sencillo que las otras funciones anteriores. Sin embargo, es un poco más detallado (deberá 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 utiliza un plan de ejecución paralelo, este es el único método garantizado para obtener la identidad (a menos que desactive el paralelismo). Sin embargo, se ejecuta antes de los disparadores y no se puede utilizar para devolver valores generados por el disparador.