В чем разница между Scope_Identity (), Identity (), @@ Identity и Ident_Current ()? - PullRequest
154 голосов
/ 17 декабря 2009

Я знаю, Scope_Identity(), Identity(), @@Identity и Ident_Current() - все получают значение столбца идентификаторов, но я бы хотел узнать разницу.

Часть противоречия, которое у меня есть, состоит в том, что они подразумевают под областью применения применительно к этим функциям выше?

Мне бы тоже понравился простой пример различных сценариев их использования?

Ответы [ 8 ]

320 голосов
/ 17 декабря 2009
  • Функция @@identity возвращает последний идентификатор, созданный в том же сеансе.
  • Функция scope_identity() возвращает последний идентификатор, созданный в том же сеансе и той же области действия.
  • ident_current(name) возвращает последний идентификатор, созданный для определенной таблицы или представления в любом сеансе.
  • Функция identity() не используется для получения идентификатора, она используется для создания идентификатора в запросе select...into.

Сеанс - это соединение с базой данных. Область действия - текущий запрос или текущая хранимая процедура.

Ситуация, когда функции scope_identity() и @@identity отличаются, если у вас есть триггер на столе. Если у вас есть запрос, который вставляет запись, в результате чего триггер вставляет куда-то еще одну запись, функция scope_identity() возвращает идентификатор, созданный запросом, а функция @@identity возвращает идентификатор, созданный триггером.

Итак, обычно вы используете функцию scope_identity().

40 голосов
/ 17 декабря 2009

Хороший вопрос.

  • @@IDENTITY: возвращает последнее значение идентификатора, созданное в вашем соединении SQL (SPID). В большинстве случаев это будет то, что вам нужно, но иногда это не так (например, когда триггер срабатывает в ответ на INSERT, а триггер выполняет другой оператор INSERT).

  • SCOPE_IDENTITY(): возвращает последнее значение идентификатора, сгенерированное в текущей области (то есть хранимая процедура, триггер, функция и т. Д.).

  • IDENT_CURRENT(): возвращает последнее значение идентификатора для конкретной таблицы. Не используйте это для получения значения идентификатора из INSERT, оно зависит от условий гонки (то есть несколько соединений вставляют строки в одну таблицу).

  • IDENTITY(): используется при объявлении столбца в таблице в качестве столбца идентификатора.

Для получения дополнительной информации см .: http://msdn.microsoft.com/en-us/library/ms187342.aspx.

Подводя итог: если вы вставляете строки и хотите знать значение идентифицирующего столбца для строки , которую вы только что вставили, всегда используйте SCOPE_IDENTITY().

14 голосов
/ 11 октября 2011

Если вы понимаете разницу между областью действия и сессией, тогда эти методы очень легко понять.

Очень хороший пост в блоге Адама Андерсона описывает эту разницу:

Сеанс означает текущее соединение, которое выполняет команду.

Область действия означает непосредственный контекст команды. Каждый вызов хранимой процедуры выполняется в своей собственной области, а вложенные вызовы выполняются во вложенной области в пределах области вызывающей процедуры. Аналогично, команда SQL, выполняемая из приложения или SSMS, выполняется в своей собственной области, и если эта команда запускает какие-либо триггеры, каждый триггер выполняется в своей собственной вложенной области.

Таким образом, различия между тремя методами поиска идентичности заключаются в следующем:

@@identity возвращает последнее значение идентификатора, сгенерированное в этом сеансе, но любая область.

scope_identity() возвращает последнее значение идентификатора, сгенерированное в этой сессии и этой области действия.

ident_current() возвращает последнее значение идентификатора, сгенерированное для конкретной таблицы в любом сеансе и любом объеме.

12 голосов
/ 17 декабря 2009

Область действия означает контекст кода, который выполняет оператор INSERT SCOPE_IDENTITY(), в отличие от глобальной области действия @@IDENTITY.

CREATE TABLE Foo(
  ID INT IDENTITY(1,1),
  Dummy VARCHAR(100)
)

CREATE TABLE FooLog(
  ID INT IDENTITY(2,2),
  LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
  INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
  INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END

INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY 

Дает разные результаты.

7 голосов
/ 31 октября 2012

Из-за ошибки, упомянутой @David Freitas, а также из-за несовместимости с новой функцией Sequence, представленной в 2012 году, я бы рекомендовал держаться подальше от всех трех из них. Вместо этого вы можете использовать предложение OUTPUT, чтобы получить вставленное значение идентификатора. Другое преимущество состоит в том, что OUTPUT работает, даже если вы вставили более одной строки.

Подробности и примеры см. Здесь: Кризис идентичности

6 голосов
/ 17 декабря 2009

Для выяснения проблемы с @@Identity:

Например, если вы вставляете таблицу, и эта таблица имеет триггеры, выполняющие вставки, @@Identity вернет идентификатор из вставки в триггере (log_id или что-то еще), а scope_identity() вернет идентификатор из вставка в исходную таблицу.

Так что если у вас нет триггеров, scope_identity() и @@identity вернут одно и то же значение. Если у вас есть триггеры, вам нужно подумать, какую ценность вы бы хотели.

3 голосов
/ 12 января 2016

Вот еще одно хорошее объяснение из книги :

Что касается разницы между SCOPE_IDENTITY и @@ IDENTITY, предположим, что у вас есть хранимая процедура P1 с тремя операторами:
- ВСТАВКА, которая генерирует новое значение идентичности
- вызов хранимой процедуры P2, которая также имеет инструкцию INSERT, которая генерирует новое значение идентификатора
- оператор, который запрашивает функции SCOPE_IDENTITY и @@ IDENTITY Функция SCOPE_IDENTITY будет возвращать значение, сгенерированное P1 (тот же сеанс и область действия). Функция @@ IDENTITY возвращает значение, сгенерированное P2 (один и тот же сеанс независимо от области действия).

3 голосов
/ 17 декабря 2009

Scope Identity: идентификатор последней записи, добавленной в выполняемую хранимую процедуру.

@@Identity: идентификатор последней записи, добавленной в пакет запроса, или в результате запроса, например, процедура, которая выполняет вставку, затем запускает триггер, который затем вставляет запись, возвращает идентификатор вставленной записи из триггера.

IdentCurrent: последний идентификатор, выделенный для таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...