В чем разница между Scope_Identity (), Identity (), @@ Identity и Ident_Current ()?

192

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

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

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

Tebo
источник
2
Не забывайте об ошибке параллельного выполнения, которая существует в SQL Server для SCOPE_IDENTITY и @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
Дэвид Д и Фрейтас,
@DaviddCeFreitas - мне любопытно прочитать об ошибке, но ссылка, похоже, не работает (или, по крайней мере, выдает ошибку ASP).
rory.ap
2
На самом деле я нашел это: support.microsoft.com/en-us/kb/2019779
rory.ap
Исправление было выпущено, как упомянуто в той старой статье KB
Джордж Бирбилис

Ответы:

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

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

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

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

Guffa
источник
14
Я выбрал это в качестве ответа из-за параграфа «Ситуация, в которой scope_identity () и @@ identity ...». Это прояснило вещи больше.
Tebo
1
Как упоминал Дэвид Фрейтас, в реализации scope_identity есть ошибка, поэтому я рекомендую использовать альтернативный метод, предложение OUTPUT. Смотрите мой ответ ниже.
Себастьян Майн
@Guffa - «Сеанс - это соединение с базой данных». Поддерживается ли сеанс через соединения, если вы используете пул соединений?
Дэйв Блэк
1
Это пример для подражания. В частности, работа с SQL и SQL Server может быть странной, и это объясняет вещи очень понятным, непрофессиональным образом, но при этом остается достаточно информативным. Это не похоже на то, как что-то сообщается между двумя специалистами по базам данных, что делают МНОГИЕ другие ответы SE.
Panzercrisis
@DaveBlack из того, что я прочитал: нет, сессия не поддерживается в пуле, сессия уникальна для вашего запуска скрипта после connect (). При создании пула ... PHP для SQL Server использует пул соединений ODBC. Когда используется соединение из пула, состояние соединения сбрасывается. Закрытие соединения возвращает соединение в пул. (примечание: см. примечания для linux / mac) docs.microsoft.com/en-us/sql/connect/php/…
GDmac
42

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

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

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

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

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

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

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

Brannon
источник
16

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

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

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

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

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

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

scope_identity()возвращает последнее значение идентичности, сгенерированное в этом сеансе, и эту область.

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

Хемант Шакта
источник
11

Область действия означает контекст кода, который выполняет 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 

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

devio
источник
6

Чтобы уточнить проблему с @@Identity:

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

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

Джонас Линкольн
источник
4

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

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

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

Андрей
источник
3

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

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

Дмитрий Докшин
источник