Какой из них является лучшим вариантом для получения значения идентификатора, которое я только что сгенерировал посредством вставки? Каково влияние этих заявлений с точки зрения производительности?
SCOPE_IDENTITY()
- Агрегатная функция
MAX()
- ВЫБЕРИТЕ
TOP 1
IdentityColumn FROM TableNameORDER BY IdentityColumn DESC
Ответы:
Используйте,
SCOPE_IDENTITY()
если вы вставляете одну строку и хотите получить сгенерированный идентификатор.Результат:
Используйте это
OUTPUT
предложение, если вы вставляете несколько строк и вам нужно получить набор сгенерированных идентификаторов.Результат:
Помимо производительности, это единственные, которые гарантированно будут правильными на уровне изоляции по умолчанию и / или для нескольких пользователей. Даже если вы игнорируете аспект правильности, SQL Server хранит вставленное значение в
SCOPE_IDENTITY()
памяти, поэтому, естественно, это будет быстрее, чем выполнение и выполнение собственного изолированного запроса к таблице или системным таблицам.Игнорирование аспекта правильности похоже на сообщение почтальону, что он хорошо справился с доставкой сегодняшней почты - он закончил свой маршрут на 10 минут быстрее, чем его среднее время, проблема в том, что ни одна почта не была доставлена в нужный дом.
Не используйте ничего из следующего:
@@IDENTITY
- поскольку это нельзя использовать во всех сценариях, например, когда в таблице со столбцом идентификаторов есть триггер, который также вставляется в другую таблицу со своим собственным столбцом идентификаторов, - вы получите неверное значение.IDENT_CURRENT()
- Я подробно расскажу об этом здесь , и комментарии также полезны для чтения, но, по сути, при параллельности вы часто получаете неправильный ответ.MAX()
илиTOP 1
- вам нужно защитить два оператора с помощью сериализуемой изоляции, чтобы гарантировать, чтоMAX()
вы получите не чужие. Это намного дороже, чем просто использоватьSCOPE_IDENTITY()
.Эти функции также завершаются сбоем всякий раз, когда вы вставляете две или более строки, и им требуются все значения идентификаторов, которые генерируются - ваш единственный вариант - это
OUTPUT
предложение.источник
Помимо производительности, все они имеют довольно разные значения.
SCOPE_IDENTITY()
даст вам последнее значение идентификатора, вставленное в любую таблицу непосредственно в текущей области (область = пакет, хранимая процедура и т. д., но не в пределах, скажем, триггера, который был запущен текущей областью).IDENT_CURRENT()
даст вам последнее значение идентификатора, вставленное в определенную таблицу из любой области, любым пользователем.@@IDENTITY
дает вам последнее значение идентификатора, сгенерированное самым последним оператором INSERT для текущего соединения, независимо от таблицы или области. (Примечание: Access использует эту функцию и поэтому имеет некоторые проблемы с триггерами, которые вставляют значения в таблицы со столбцами идентификаторов.)Использование
MAX()
илиTOP 1
может дать вам совершенно неверные результаты, если таблица имеет шаг отрицательной идентификации или в нее вставлены строкиSET IDENTITY_INSERT
. Вот скрипт, демонстрирующий все это:Резюме: палка
SCOPE_IDENTITY()
,IDENT_CURRENT()
или@@IDENTITY
, и убедитесь , что вы используете тот , который возвращает то , что вы на самом деле нужно.источник
IDENT_CURRENT()
и@@IDENTITY
когда ваш собственный скрипт демонстрирует, что они выдают неверные результаты?IDENT_CURRENT()
возвращается. MAX () никогда не возвращает правильное значение за пределами первой строки, так как id считается в обратном направлении, а приIDENTITY_INSERT
включении 9005 не является сгенерированным значением идентификатора, поэтому не отражаетсяIDENT_CURRENT()
. Но он может вернуть «неправильные» результаты, если вы действительно после того, чтоSCOPE_IDENTITY()
возвращает. Выберите правильный инструмент для работы.@@IDENTITY
это почти никогда не идеальный способ получить сгенерированные значения идентичности. Суть в том, чтоMAX()
илиTOP 1
они похожи на менее надежную версиюIDENT_CURRENT()
, что прекрасно подходит для использования, если вы понимаете, что она делает. Может быть полезно для работ по техническому обслуживанию или что-то.