Использование идентификатора в SQL Server без условия гонки

#sql #sql-server

#sql #sql-сервер

Вопрос:

Итак, допустим, у вас есть таблица пациентов с идентификатором (1,1) для первичного ключа. Используя @@Identity, как мы можем избежать состояния гонки, когда два человека могут одновременно спасти нового пациента? Очевидно, что дубликаты идентификаторов в таблице пациентов не будут созданы, но что, если приложению потребуется идентификатор для одного из вставленных пациентов, чтобы обновить запись в другой таблице в другом месте? Откуда мы знаем, что @@Identity не получит идентификатор другой записи, если обе будут вставлены одновременно?

Или есть ли лучшая практика, чтобы избежать этого?

JamesNT

Комментарии:

1. Ну, во-первых, вы используете SCOPE_IDENTITY(), а не @@IDENTITY. И о каком состоянии гонки вы говорите? Одна вставка выиграет и получит первую строку, а затем последует другая вставка. Каждая вставка получит обратно свое собственное значение SCOPE_IDENTITY(), одна вставка не сможет получить значение другой.

Ответ №1:

Да, есть лучшая практика. Не используйте @@Identity .

Самый безопасный способ получить значения идентификатора, присвоенные в insert инструкции, — это использовать OUTPUT предложение. Вы должны начать с документации.

Это имеет множество преимуществ:

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

Комментарии:

1. Похоже, у нас есть связь между SCOPE_IDENTITY и выводом.

2. Как нам разорвать эту связь?

3. Мне нужно иметь возможность проверять ОБА ответа, поскольку они оба, похоже, работают.

4. ВЫВОД отлично подходит для возврата только что введенной строки, включая идентификатор. Но scope-identity также отлично работает и подходит для моих нужд.

5. @JamesNT . . . Общий консенсус заключается в том, что OUTPUT это более надежный, гибкий и безопасный.

Ответ №2:

@@IDENTITY не вызовет состояние гонки, но это также НЕ лучшая практика. Вместо этого вы должны использовать SCOPE_IDENTITY.

http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

Комментарии:

1. Итак, я делаю ВСТАВКУ, но затем должен выполнить ВЫБОР в SCOPE_IDENTITY. Вопрос: Как мне справиться с возможностью того, что между завершением моей ВСТАВКИ и запуском SELECT кто-то не вставит запись за это время? Прошу прощения, если я звучу как n00b.

2. Вам не нужно беспокоиться об этом. Если другой процесс вставляет строку, это будет другое соединение… таким образом, область действия будет совершенно другой.