Яка різниця між Scope_Identity (), Identity (), @@ Identity та Ident_Current ()?


192

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

Частина суперечки, яку я маю, - це те, що вони означають під сферою застосування, що застосовується до цих функцій вище?

Я також хотів би простий приклад різних сценаріїв їх використання?


2
Не забувайте про помилку паралельного виконання, яка існує в SQL Server для SCOPE_IDENTITY та @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas

@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()функцію.


14
Я вибрав це як відповідь через абзац "Ситуація, коли obsegidentity () та ідентифікатор @@ ...". Це детальніше прояснило речі.
Тебо

1
Як згадував Девід Фрейтас вище, у впровадженні obseg_identity є помилка, тому я рекомендую використовувати альтернативний метод, пункт OUTPUT. Дивіться мою відповідь нижче.
Себастьян Мейн

@Guffa - "Сеанс - це з'єднання з базою даних". Чи підтримується сеанс через з'єднання, якщо ви використовуєте Пул з'єднання?
Дейв Блек

1
Це відповідь для наслідування. Зокрема, робота з SQL та SQL Server може бути дивною, і це пояснює речі дуже чітко, непросто, але при цьому залишається досить інформативним. Це не схоже на те, що щось спілкується між двома спеціалістами по базі даних, що робить багато інших відповідей SE.
Panzercrisis

@DaveBlack з того, що я прочитав: Ні, сеанс не підтримується в пулі, сеанс унікальний для запуску сценарію після підключення (). Під час об'єднання ... 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().


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 

Дає різні результати.


9

Через помилку, про яку згадував @David Freitas, і через несумісність з новою функцією Sequence, яка була представлена ​​в 2012 році, я б рекомендував триматися подалі від усіх цих трьох. Натомість ви можете використовувати пункт OUTPUT, щоб отримати вставлене значення ідентичності. Інша перевага полягає в тому, що OUTPUT працює навіть якщо ви вставили більше одного ряду.

Деталі та приклади див. Тут: Криза ідентичності


Я думаю, що ця відповідь заслуговує більшої уваги.
сир

На жаль, INSERT ... OUTPUT Inserted.xx не працює з тригерами INSERT (те саме стосується тригерів UPDATE ... OUTPUT Updated.xx та UPDATE). Вони пропонують використовувати INSERT ... OUTPUT INTO, але це занадто багатослівно, а використання цього у клієнтів (замість збережених програм) є проблематичним. ВСТАВКА ... OUTPUT Inserted.xx прекрасний при використанні з дзвінками на стороні клієнта (просто потрібен ExecuteScalar, щоб зробити вставку і сказати повернути автогенерований ідентифікатор для нового рядка), якщо вам не потрібні тригери.
Джордж Бірбіліс

Виправлено цю помилку? минуло 8 років з того часу, як написана стаття
допатраман

6

Щоб уточнити проблему за допомогою @@Identity:

Наприклад, якщо ви вставляєте таблицю, а у цій таблиці є тригери, які роблять вставки, @@Identityповертає ідентифікатор зі вставки в тригері ( 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 (той самий сеанс, незалежно від сфери застосування).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.