¿Cuál es la mejor opción para obtener el valor de identidad que acabo de generar mediante una inserción? ¿Cuál es el impacto de estas declaraciones en términos de desempeño?
SCOPE_IDENTITY()
- Función agregada
MAX()
- SELECT
TOP 1
IdentityColumn FROM TableNameORDER BY IdentityColumn DESC
Respuestas:
Úselo
SCOPE_IDENTITY()
si está insertando una sola fila y desea recuperar la ID que se generó.Resultado:
Use la
OUTPUT
cláusula si está insertando varias filas y necesita recuperar el conjunto de ID que se generaron.Resultado:
Dejando de lado el rendimiento, estos son los únicos que se garantiza que son correctos en el nivel de aislamiento predeterminado y / o con múltiples usuarios. Incluso si ignora el aspecto de corrección, SQL Server mantiene el valor insertado
SCOPE_IDENTITY()
en la memoria, por lo que, naturalmente, será más rápido que ejecutar y ejecutar su propia consulta aislada en la tabla o en las tablas del sistema.Ignorar el aspecto de corrección es como decirle al cartero que hizo un buen trabajo entregando el correo de hoy: terminó su ruta 10 minutos más rápido que su tiempo promedio, el problema es que ninguno de los correos se entregó a la casa correcta.
No use ninguno de los siguientes:
@@IDENTITY
- ya que esto no se puede usar en todos los escenarios, por ejemplo, cuando una tabla con una columna de identidad tiene un activador que también se inserta en otra tabla con su propia columna de identidad, obtendrá el valor incorrecto.IDENT_CURRENT()
- de entrar en detalles sobre esto aquí , y los comentarios leyendo útil también, pero en esencia, en virtud de la concurrencia, a menudo obtendrá la respuesta equivocada.MAX()
oTOP 1
- tendría que proteger las dos declaraciones con aislamiento serializable para asegurarse de que loMAX()
que obtiene no sea de otra persona. Esto es mucho más costoso que solo usarloSCOPE_IDENTITY()
.Estas funciones también fallan cada vez que inserta dos o más filas y necesita todos los valores de identidad generados; su única opción es la
OUTPUT
cláusula.fuente
Además del rendimiento, todos tienen significados bastante diferentes.
SCOPE_IDENTITY()
le dará el último valor de identidad insertado en cualquier tabla directamente dentro del alcance actual (alcance = lote, procedimiento almacenado, etc. pero no dentro, por ejemplo, de un disparador que fue disparado por el alcance actual).IDENT_CURRENT()
le dará el último valor de identidad insertado en una tabla específica desde cualquier ámbito, por cualquier usuario.@@IDENTITY
le proporciona el último valor de identidad generado por la instrucción INSERT más reciente para la conexión actual, independientemente de la tabla o el alcance. (Nota al margen: Access usa esta función y, por lo tanto, tiene algunos problemas con los desencadenantes que insertan valores en tablas con columnas de identidad).Usar
MAX()
oTOP 1
puede darle resultados completamente incorrectos si la tabla tiene un paso de identidad negativo, o si ha insertado filasSET IDENTITY_INSERT
en juego. Aquí hay un script que demuestra todo esto:Resumen: palo con
SCOPE_IDENTITY()
,IDENT_CURRENT()
o@@IDENTITY
, y asegurarse de que está usando el que vuelve lo que realmente necesita.fuente
IDENT_CURRENT()
y@@IDENTITY
cuando su propio script demuestra que generan resultados incorrectos?IDENT_CURRENT()
devuelve. MAX () nunca devuelve el valor correcto más allá de la primera fila, ya que id está contando hacia atrás, y conIDENTITY_INSERT
on, 9005 no es un valor de identidad generado , por lo tanto, no se refleja enIDENT_CURRENT()
. Pero puede devolver resultados "incorrectos" si realmente busca lo queSCOPE_IDENTITY()
devuelve. Elija la herramienta adecuada para el trabajo.@@IDENTITY
casi nunca es la forma ideal de obtener valores de identidad generados. El punto principal es esoMAX()
oTOP 1
son como una versión menos confiable deIDENT_CURRENT()
, que es una función perfectamente buena para usar si entiendes lo que hace. Podría ser útil para trabajos de mantenimiento o algo así.