Sql Server 2005 – вставить, если не существует
В Интернете есть много информации об этой общей «проблеме».
Решения, такие как:
IF NOT EXISTS() BEGIN INSERT INTO (...) END
по моему мнению, не являются потокобезопасными, и вы, вероятно, согласитесь.
- Какой уровень изоляции используется для предотвращения чтения данных?
- Невозможно использовать READPAST в режиме изоляции моментальных снимков
- Для дешевой / быстрой транзакции без котировок: COMMIT или ROLLBACK?
- Как откат, если какое-либо обновление не является успешным?
- Какой тип Transaction IsolationLevel следует использовать для игнорирования вставок, но блокировка выбранной строки?
Однако не могли бы вы подтвердить, что включение существующего в предложение where одного единственного выбора решит проблему наивысшего параллелизма в SQL-движке? Это достаточно?
insert into Table (columns) select column1, column2, column3 where not exists (select top 1 1 from Table where something)
Должен ли быть добавлен и более высокий уровень транзакции, или это может быть выполнено по умолчанию: зафиксировано?
Будет ли это работать на неограниченном уровне?
Благодаря!
// Добавлено позже
Могу ли я предположить, что оба sql 'верны:
1) установить уровень изоляции транзакции
IF NOT EXISTS() BEGIN INSERT INTO (...) END
2) установить уровень изоляции транзакции
insert into Table (columns) select column1, column2, column3 where not exists (select top 1 1 from Table where something)
- Эффективная транзакция, блокировка записи
- SQL-транзакции (b) Блокировка Выбор - это мое понимание правильно
- Столбцы идентификаторов для схем многозадачных баз данных
- Вставка RollBack в несколько таблиц в SQL Server 2005
- Вложенные транзакции SQL в SQL Server
- Сделка SQL Server 2008, требуется возврат?
- Эта хорошая транзакция записи в хранимой процедуре
- Реализация транзакций по нескольким базам данных
С помощью TRY / CATCH вы можете избежать дополнительного чтения
BEGIN TRY INSERT etc END TRY BEGIN CATCH IF ERROR_NUMBER() <> 2627 RAISERROR etc END CATCH
- НЕ СУЩЕСТВУЕТ прочитать таблицу, будь то в IF или WHERE
- INSERT требует чтения для проверки уникальности
Если вы можете отказаться от дубликатов, это очень масштабируемый метод
Ссылки:
- См. Мои ответы здесь: только вставка строки, если она еще не существует, и SQL Server 2008: INSERT, если не завершает работу, поддерживает уникальный столбец
- Если вам также нужны ОБНОВЛЕНИЯ: какой из них лучше всего использовать в delete-insert vs if-update else-insert?
Чтобы ответить на обновленный вопрос, repeatable read
все равно будет недостаточным.
Это уровень holdlock
/ serializable
который вам нужен.
Вы пытаетесь предотвратить фантомы (где при первом чтении ни одна строка не соответствовала критериям, поэтому NOT EXISTS
возвращает true, но впоследствии параллельная транзакция вставляет строку, соответствующую ей)