Разница между @@IDENTITY, SCOPE_IDENTITY() и IDENT_CURRENT в SQL Serversql-39

1. Основные различия

Эти функции возвращают последнее значение идентификатора, но работают по-разному:

ФункцияОбласть действияУчитывает триггерыБезопасностьКонкретная таблица
@@IDENTITYВсе сеансыДаНизкаяНет
SCOPE_IDENTITY()Текущая область видимостиНетВысокаяНет
IDENT_CURRENT()Указанная таблицаН/ДСредняяДа

2. Подробное описание каждой функции

@@IDENTITY

Возвращает последнее значение IDENTITY, сгенерированное в любом таблице текущего сеанса, включая сработавшие триггеры.

INSERT INTO Orders (CustomerID) VALUES ('ALFKI');
SELECT @@IDENTITY AS LastID; -- Может вернуть ID из триггера

Проблема: Если после вашего INSERT сработает триггер, который тоже вставляет данные в таблицу с IDENTITY, вы получите не тот ID.

SCOPE_IDENTITY

Возвращает последнее значение IDENTITY, сгенерированное в текущей области видимости (ваш запрос или хранимая процедура), игнорируя триггеры.

INSERT INTO Orders (CustomerID) VALUES ('ALFKI');
SELECT SCOPE_IDENTITY() AS LastID; -- Вернет ID из Orders

Рекомендуется использовать всегда, если нужно получить ID только что вставленной записи.

IDENT_CURRENT

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

SELECT IDENT_CURRENT('Orders') AS LastOrderID; -- Последний ID в таблице Orders

Особенности:

  • Не зависит от вашего сеанса
  • Может вернуть значение, сгенерированное другим пользователем

3. Когда что использовать?

SCOPE_IDENTITY() - в 95% случаев:

  • После INSERT в хранимых процедурах
  • В прикладном коде

@@IDENTITY - почти никогда (только если нужно значение из триггера)

IDENT_CURRENT() - для административных задач:

  • Мониторинг
  • Отладочные запросы

4. Пример с триггером

CREATE TRIGGER tr_OrderDetails
ON Orders AFTER INSERT
AS
BEGIN
    INSERT INTO OrderLogs (OrderID, LogDate)
    SELECT OrderID, GETDATE() FROM inserted;
END;

-- Тестовый запрос
INSERT INTO Orders (CustomerID) VALUES ('ALFKI');
SELECT
    @@IDENTITY AS [@@IDENTITY],         -- Вернет ID из OrderLogs
    SCOPE_IDENTITY() AS [SCOPE_IDENTITY], -- Вернет ID из Orders
    IDENT_CURRENT('Orders') AS [Orders ID],
    IDENT_CURRENT('OrderLogs') AS [Logs ID];

5. Особенности параллельной работы

В многопользовательской среде:

  • @@IDENTITY и SCOPE_IDENTITY() возвращают значения только вашего сеанса
  • IDENT_CURRENT() может вернуть значение, сгенерированное другим пользователем

6. Производительность

Все три функции работают мгновенно, так как:

  • @@IDENTITY и SCOPE_IDENTITY() берут значения из памяти
  • IDENT_CURRENT() делает быстрый lookup в системных таблицах

Резюмируем: для получения ID только что вставленной записи всегда используйте SCOPE_IDENTITY(). @@IDENTITY опасен из-за триггеров, а IDENT_CURRENT() полезен для административных задач, но не для работы с конкретными вставками.