Мне не удалось найти ответ на этот вопрос. Предположим, у меня есть следующая таблица/запрос:Избегайте вставки повторяющихся записей в SQL Server
Стол:
create table ##table
(
column1 int,
column2 nvarchar(max)
)
Запрос (в реальном сценарии жизни состояние будет более сложным):
declare @shouldInsert bit
set @shouldInsert = case when exists(
select *
from ##table
where column2 = 'test') then 1 else 0 end
--Exaggerating a possible delay:
waitfor delay '00:00:10'
if(@shouldInsert = 0)
insert into ##table
values(1, 'test')
Если я запускаю этот дважды, тогда он может вставить дубликаты записей (ограничение уникального ограничения не может быть и речи, потому что реальное условие более активно, чем просто уникальность «column1» по всей таблице).
Я вижу два возможных решения:
я бег оба параллельных транзакций в сериализуемой режиме, но это создаст затор (первый общий замок в выбери то х-замок в вкладыше - тупиковый).
В отборном заявлении я использую запрос подсказку с (обновлением, TABLOCK), который будет эффективно рентгеновским заблокировать всю таблицу, но это будет препятствовать другие транзакциям чтения данных (что-то я хотел бы избежать)
Что более приемлемо? Есть ли третье решение?
Спасибо.
Нельзя использовать LEFT JOIN 'insert в ## table SELECT t.col1, t.col2 FROM (SELECT 1 as col1, 'test' as col2) t LEFT JOIN ## table temp ON t.col1 = temp.col1 WHERE temp.col1 IS NULL'? – lad2025
Вы считали объединение теста shouldInsert и фактической вставки в один оператор SQL. Что-то в строках «insert into ## table (выберите 1,« test »из dual, где не существует ...» –
Я бы выбрал второе решение, но с помощью 'INSERT ... SELECT ... WHERE NOT Синтаксис EXISTS с подсказкой блокировки в подзапросе.Я бы не ожидал, что параллелизм будет проблемой, если у вас очень высокая скорость вставки, предполагая уникальный индекс в столбце2. –