Как узнать идентификатор при insert'е в T-SQL? - CodeHelper

Как узнать идентификатор при insert'е в T-SQL?

1

Я вставляю запись в таблицу инсертом, как мне узнать id новой записи? Паралельно могут выполняться тысячи операций insert'ов в эту же таблицу, как узнать id правильно? Т.е. как я понимаю надо сделать инсерт и взятие значения из @@identity одновременно? Вставка выплняется в сторе процедуре.

Новые ответы


0

Функция @@IDENTITY возвращает последнее значение, записанное севером в автоинкрементный столбец в текущей сессии. Что это означает? Если между вызовом INSERT и вызовом @@IDENTITY успеет пролезть вставка из другой сессии, то @@IDENTITY вернет идентификатор, который был записан при первой вставке. То есть, при пользовании @@IDENTITY нет необходимости заботиться о том, что параллельные вставки будут мешать друг другу при получении правильных идентификаторов, сервер все сделает сам.

---- Session 1:
INSERT INTO Ident_table (some_values) VALUES ('value 5')

---- Session 2:
INSERT INTO Ident_table (some_values) VALUES ('value 6')

---- Session 1:
SELECT @@IDENTITY as [Last ID in session]
SELECT * FROM Ident_table

--- результат:
Last ID in session                       
---------------------------------------- 
7

(1 row(s) affected)

ID          some_values                                        
----------- ---------------------------- 
...         ...
6           value 4
7           value 5
8           value 6

(6 row(s) affected)

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

-- еще одна табличка с автоинкрементом CREATE TABLE Ident2(ID int IDENTITY(0, -2), value varchar(50)) GO

-- триггер на вставку к первоначальной табличке
CREATE TRIGGER IdentTrigger ON Ident_table
FOR INSERT
AS
INSERT INTO Ident2 (value) VALUES(GetDate())
GO

-- добавление еще одной записи
INSERT INTO Ident_table (some_values) VALUES ('value 7')

-- наслаждение результатом...
SELECT @@IDENTITY as [Last ID in session (@@IDENTITY)]
SELECT SCOPE_IDENTITY() as [Last ID in batch (SCOPE_IDENTITY())]
SELECT * FROM Ident_table

--- результат:
Last ID in session (@@IDENTITY)                      
---------------------------------------- 
0

Last ID in batch (SCOPE_IDENTITY())                        
---------------------------------------- 
9

ID          some_values                                        
----------- ---------------------------- 
...         ...
8           value 6
9           value 7

(7 row(s) affected)

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

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

Собственно этот пример и демонстрирует различия всех трех способов получения записанного сервером значения автоинкремента. Эти способы покрывают практически все потребности в автоинкрементах, которые могут возникнуть при разработке.

Источник

0

Попробуй SCOPE_IDENTITY()

Возвращает последнее значение идентификатора, вставленное в столбец идентификаторов в той же области. Областью является модуль, что подразумевает хранимую процедуру, триггер, функцию или пакет. Таким образом, две инструкции принадлежат одной и той же области, если они находятся в одной и той же хранимой процедуре, функции или пакете.

подробнее в MSDN


v1.7.123.556
© 2009—2010 CodeHelper FAQ | О сайте | Обратная связь | История изменений | Статьи
Creative Commons LicenseМатериалы сайта распространяются под лицензией Creative Commons Attribution-Share Alike 3.0 Unported.