В чем разница между Scope_Identity(), Identity(), @@Identity и Ident_Current()?
Я знаю Scope_Identity()
, Identity()
, @@Identity
, а также Ident_Current()
все получают значение столбца идентификации, но я бы хотел узнать разницу.
Часть противоречия, которое я имею, состоит в том, что они подразумевают под областью применительно к этим функциям выше?
Я также хотел бы простой пример различных сценариев их использования?
8 ответов
@@identity
Функция возвращает последний идентификатор, созданный в том же сеансе.scope_identity()
Функция возвращает последний идентификатор, созданный в том же сеансе и той же области видимости.ident_current(name)
возвращает последний идентификатор, созданный для определенной таблицы или представления в любом сеансе.identity()
Функция не используется для получения идентичности, она используется для создания идентичности вselect...into
запрос.
Сеанс - это соединение с базой данных. Область действия - текущий запрос или текущая хранимая процедура.
Ситуация, когда scope_identity()
и @@identity
Функции отличаются, если у вас есть триггер на столе. Если у вас есть запрос, который вставляет запись, в результате чего триггер вставляет куда-то другую запись, scope_identity()
функция вернет идентификатор, созданный запросом, а @@identity
Функция вернет идентичность, созданную триггером.
Итак, обычно вы бы использовали scope_identity()
функция.
Хороший вопрос.
@@IDENTITY
: возвращает последнее значение идентификатора, сгенерированное в вашем соединении SQL (SPID). В большинстве случаев это будет то, что вы хотите, но иногда это не так (например, когда срабатывает триггер в ответ наINSERT
и триггер выполняет другойINSERT
заявление).SCOPE_IDENTITY()
: возвращает последнее значение идентификатора, сгенерированное в текущей области (т.е. хранимая процедура, триггер, функция и т. д.).IDENT_CURRENT()
: возвращает последнее значение идентификатора для конкретной таблицы. Не используйте это, чтобы получить значение идентичности отINSERT
, это зависит от условий гонки (то есть несколько соединений вставляют строки в одну таблицу).IDENTITY()
: используется при объявлении столбца в таблице как столбца идентификаторов.
Для получения дополнительной информации см.: http://msdn.microsoft.com/en-us/library/ms187342.aspx.
Подводя итог: если вы вставляете строки и хотите знать значение столбца идентификаторов для только что вставленной строки, всегда используйте SCOPE_IDENTITY()
,
Если вы понимаете разницу между областью действия и сессией, то эти методы будут очень легко понять.
Очень хорошая запись в блоге Адама Андерсона описывает эту разницу:
Сеанс означает текущее соединение, которое выполняет команду.
Область действия означает непосредственный контекст команды. Каждый вызов хранимой процедуры выполняется в своей собственной области, а вложенные вызовы выполняются во вложенной области в пределах области вызывающей процедуры. Аналогично, команда SQL, выполняемая из приложения или SSMS, выполняется в своей собственной области, и если эта команда запускает какие-либо триггеры, каждый триггер выполняется в своей собственной вложенной области.
Таким образом, различия между тремя методами поиска идентичности заключаются в следующем:
@@identity
возвращает последнее значение идентификатора, сгенерированное в этом сеансе, но любую область.
scope_identity()
возвращает последнее значение идентификатора, сгенерированное в этом сеансе, и эту область.
ident_current()
возвращает последнее значение идентификатора, сгенерированное для конкретной таблицы в любом сеансе и любой области видимости.
Область действия означает контекст кода, который выполняет 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
Дает разные результаты.
Из-за ошибки, упомянутой @David Freitas, и из-за несовместимости с новой функцией Sequence, которая была представлена в 2012 году, я бы рекомендовал держаться подальше от всех трех из них. Вместо этого вы можете использовать предложение OUTPUT, чтобы получить вставленное значение идентификатора. Другое преимущество состоит в том, что OUTPUT работает даже, если вы вставили более одной строки.
Подробности и примеры смотрите здесь: Identity Crisis
Scope Identity
: Идентификатор последней записи, добавленной в хранимую процедуру, которая выполняется.
@@Identity
: Идентификация последней записи, добавленной в пакете запроса, или в результате запроса, например, процедура, которая выполняет вставку, затем запускает триггер, который затем вставляет запись, возвращает идентификатор вставленной записи из триггера.
IdentCurrent
: Последний идентификатор, выделенный для таблицы.
Чтобы прояснить проблему с @@Identity
:
Например, если вы вставляете таблицу, и эта таблица имеет триггеры, делающие вставки, @@Identity
вернет идентификатор из вставки в триггере (log_id
или что-то), в то время как scope_identity()
вернет идентификатор из вставки в исходной таблице.
Так что если у вас нет никаких триггеров, scope_identity()
а также @@identity
вернет то же значение. Если у вас есть триггеры, вам нужно подумать, какую ценность вы бы хотели.
Вот еще одно хорошее объяснение из книги:
Что касается различия между SCOPE_IDENTITY и @@IDENTITY, предположим, что у вас есть хранимая процедура P1 с тремя инструкциями:
- ВСТАВКА, которая генерирует новое значение идентичности
- вызов хранимой процедуры P2, которая также имеет инструкцию INSERT, которая генерирует новое значение идентификатора
- Оператор, который запрашивает функции SCOPE_IDENTITY и @@ IDENTITY Функция SCOPE_IDENTITY возвращает значение, сгенерированное P1 (тот же сеанс и область действия). Функция @@ IDENTITY будет возвращать значение, сгенерированное P2 (один и тот же сеанс независимо от области видимости).