¿Cuál es la mejor manera de obtener una IDENTITYfila insertada?
Sé acerca de @@IDENTITYy IDENT_CURRENTy SCOPE_IDENTITYpero no entiendo los pros y los contras asociados a cada uno.
¿Alguien puede explicar las diferencias y cuándo debería usarlas?
sql
sql-server
tsql
Oded
fuente
fuente

INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...), o un método anterior:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();puede obtenerlo en C # usando ExecuteScalar ().OUTPUTcláusula en SQL Server.Respuestas:
@@IDENTITYdevuelve el último valor de identidad generado para cualquier tabla en la sesión actual, en todos los ámbitos. Debe tener cuidado aquí , ya que está en todos los á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 los 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
OUTPUTcláusula de laINSERTdeclaración le permitirá acceder a cada fila que se insertó a través de esa declaración. Dado que está enfocado a 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 en paralelo, este es el único método garantizado para obtener la identidad (salvo desactivar el paralelismo). Sin embargo, se ejecuta antes de los disparadores y no se puede usar para devolver valores generados por disparadores.fuente
outputusted no necesita crear una tabla temporal para almacenar y consultar los resultados. Simplemente omita laintoparte de la cláusula de salida y los enviará a un conjunto de resultados.OUTPUTes la "mejor" siempre y cuando no estés usando disparadores y estés manejando errores, peroSCOPE_IDENTITYes el más simple y rara vez tiene problemasCreo 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 )
fuente
OUTPUTen SQL Server 2005 , por lo que parece que solo SQL Server 2000 yEstoy diciendo lo mismo que los otros chicos, así que todos están en lo correcto, solo estoy tratando de dejarlo más claro.
@@IDENTITYdevuelve la identificación 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 activará un disparador e insertará una nueva fila que desconoce, y obtendrá la ID de esta nueva fila, en lugar de la que desea
SCOPE_IDENTITY()resuelve este problema Devuelve la identificación de lo último que insertó en el código SQL que envió a la base de datos. Si los disparadores van y crean filas adicionales, no harán que se devuelva el valor incorrecto. HurraIDENT_CURRENTdevuelve la última identificación que fue insertada por cualquiera. Si alguna otra aplicación inserta otra fila en un momento desafortunado, obtendrá la ID de esa fila en lugar de la suya.Si quieres jugar a lo seguro, úsalo siempre
SCOPE_IDENTITY(). Si te quedas@@IDENTITYy alguien decide agregar un disparador más adelante, todo tu código se romperá.fuente
La mejor manera (léase: la más segura) de obtener la identidad de una fila recién insertada es mediante la
outputcláusula:fuente
scope_identity()) obtengan planes paralelos de todos modos. Y este error se solucionó más de un año antes de esta respuesta.outputlugar descope_identity(). He eliminado el FUD sobre la agrupación en la respuesta.Añadir
hasta el final de su instrucción sql de inserción, luego
Lo recuperará.
fuente
Cuando usa Entity Framework, usa internamente la
OUTPUTtécnica para devolver el valor de ID recién insertadoLos resultados de salida se almacenan en una variable de tabla temporal, se unen de nuevo a la tabla y devuelven el valor de fila de la tabla.
Nota: No tengo idea de por qué EF uniría internamente la tabla efímera a la tabla real (en qué circunstancias los dos no coincidirían).
Pero eso es lo que hace EF.
Esta técnica (
OUTPUT) solo está disponible en SQL Server 2008 o posterior.Editar : el motivo de la unión
La razón por la que Entity Framework se une a la tabla original, en lugar de simplemente usar los
OUTPUTvalores, es porque EF también usa esta técnica para obtener larowversionfila recién insertada.Puede usar la concurrencia optimista en los modelos de marco de su entidad utilizando el
Timestampatributo: 🕗Cuando haga esto, Entity Framework necesitará
rowversionla nueva fila insertada:Y para recuperar esto
Timetsampno puede usar unaOUTPUTcláusula.Esto se debe a que si hay un disparador en la mesa, cualquier
Timestampsalida que realice estará mal:La marca de tiempo devuelta nunca será correcta si tiene un activador en la tabla. Entonces debes usar un separado
SELECT.E incluso si estuviera dispuesto a sufrir la versión incorrecta de la fila, la otra razón para realizar una separación
SELECTes que no puede SALIR unarowversionvariable de tabla:La tercera razón para hacerlo es por simetría. Al realizar un
UPDATEsobre una mesa con un disparador, no puede usar unaOUTPUTcláusula. Intentar hacerUPDATEcon unOUTPUTno es compatible, y dará un error:La única forma de hacerlo es con una
SELECTdeclaración de seguimiento :fuente
TurboEncabulators:)MSDN
fuente
@@ IDENTITY es la última identidad insertada utilizando la conexión SQL actual. Este es un buen valor para regresar de un procedimiento almacenado de inserción, donde solo necesita la identidad insertada para su nuevo registro, y no le 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 hubo una segunda IDENTIDAD insertada en función de 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.
fuente
No puedo hablar con otras versiones de SQL Server, pero en 2012, la salida directamente funciona bien. No necesita molestarse con una mesa temporal.
Por cierto, esta técnica también funciona al insertar varias filas.
Salida
fuente
OUTPUT. Si no necesita la tabla temporal, su consulta termina siendo mucho más simple.SIEMPRE use scope_identity (), NUNCA hay necesidad de nada más.
fuente
Cree un
uuidy también insértelo en una columna. Entonces puede identificar fácilmente su fila con el uuid. Esa es la única solución 100% funcional que puede implementar. Todas las demás soluciones son demasiado complicadas o no funcionan en los mismos casos extremos. P.ej:1) Crear fila
2) Obtener fila creada
fuente
uuiden la base de datos. Entonces la fila se encontrará más rápido.https://www.npmjs.com/package/uuid.const uuidv4 = require('uuid/v4'); const uuid = uuidv4()Otra forma de garantizar la identidad de las filas que inserte es especificar los valores de identidad y usar el
SET IDENTITY_INSERT ONy luegoOFF. ¡Esto garantiza que sepa exactamente cuáles son los valores de identidad! Mientras los valores no estén en uso, puede insertar estos valores en la columna de identidad.Esta puede ser una técnica muy útil si está cargando datos de otra fuente o fusionando datos de dos bases de datos, etc.
fuente
Aunque este es un subproceso anterior, hay una forma más nueva de hacerlo que evita algunos de los escollos de la columna IDENTIDAD en las versiones anteriores de SQL Server, como las brechas en los valores de identidad después de reiniciar el servidor . Las secuencias están disponibles en SQL Server 2016 y el reenvío, que es la forma más nueva, es crear un objeto SECUENCIA usando TSQL. Esto le permite crear su propio objeto de secuencia numérica en SQL Server y controlar cómo se incrementa.
Aquí hay un ejemplo:
Luego, en TSQL, haría lo siguiente para obtener la siguiente ID de secuencia:
Aquí están los enlaces para CREAR SECUENCIA y SIGUIENTE VALOR PARA
fuente
Después de su declaración de inserción, debe agregar esto. Y asegúrese del nombre de la tabla donde se insertan los datos. Obtendrá la fila actual sin la fila afectada justo ahora por su instrucción de inserción.
fuente