SQL Server: вставка записей в таблицу, если их нет

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если требуется вставить данные в отсутствии дубликатов, воспользуйтесь следующим запросом:

SQL
Скопировать код
INSERT INTO ВашаТаблица (Колонка1, Колонка2)
SELECT Значение1, Значение2
WHERE NOT EXISTS (
    SELECT 1 FROM ВашаТаблица WHERE НекаяКолонка = НекоеЗначение
)

Замените идентификаторы колонок и соответствующие значения в вашей таблице. Данный запрос с использованием WHERE NOT EXISTS проверяет избежание дублирования и сокращает код без потери функциональности.

Кинга Идем в IT: пошаговый план для смены профессии

Проблема гонок состояний

Будьте в курсе возможных гонок состояний. Они происходят, когда другая транзакция вставляет аналогичные данные между моментом проверки и выполнением INSERT. Чтобы минимизировать этот риск, используйте уровни изоляции транзакций или блокировки таблиц:

SQL
Скопировать код
BEGIN TRANSACTION;
IF NOT EXISTS (SELECT * FROM ВашаТаблица WHERE НекаяКолонка = НекоеЗначение)
BEGIN
    INSERT INTO ВашаТаблица (Колонка1, Колонка2) VALUES (Значение1, Значение2);
END;
COMMIT TRANSACTION;

Использование MERGE для условной вставки

Для условной вставки рекомендуется использовать MERGE:

SQL
Скопировать код
MERGE INTO ВашаТаблица AS Цель
USING (VALUES (Значение1, Значение2)) AS Источник (Колонка1, Колонка2)
ON Цель.НекаяКолонка = Источник.НекаяКолонка
WHEN NOT MATCHED THEN
    INSERT (Колонка1, Колонка2)
    VALUES (Источник.Колонка1, Источник.Колонка2);

При применении MERGE проявляйте осторожность, поскольку это может повлиять на производительность при интенсивной параллельной работе.

Борьба с дублированием данных при помощи подзапросов и соединений

Для сложных проверок на существование данных, воспользуйтесь подзапросом или LEFT JOIN:

SQL
Скопировать код
INSERT INTO ВашаТаблица (Колонка1, Колонка2, ...)
SELECT temp.Колонка1, temp.Колонка2, ...
FROM (
    SELECT Значение1 AS Колонка1, Значение2 AS Колонка2, ...
) AS temp
LEFT JOIN ВашаТаблица ON ВашаТаблица.НекаяКолонка = temp.Колонка1
WHERE ВашаТаблица.НекаяКолонка IS NULL;

Для опытных специалистов (работа с большими объёмами данных)

При работе с большими объёмами данных важно обратить особое внимание на производительность методов вставки и искать путей их оптимизации:

SQL
Скопировать код
BEGIN TRANSACTION;
IF NOT EXISTS (SELECT * FROM ВашаТаблица WHERE НекаяКолонка = НекоеЗначение)
BEGIN
    INSERT INTO ВашаТаблица (Колонка1, Колонка2) VALUES (Значение1, Значение2);
END;
COMMIT TRANSACTION;

Визуализация

Приведем аналогию. Вы ответственны за гардероб на съемочной площадке голливудского блокбастера и обязаны предоставить каждому костюму конкретный шкафчик:

Markdown
Скопировать код
Гардероб: [Костюм1, Костюм2, Костюм3, ...]

Функция INSERT if not exists служит как распределитель шкафчиков для новых костюмов, при условии, что у них еще нет собственного места:

SQL
Скопировать код
IF NOT EXISTS (SELECT * FROM Гардероб WHERE ID='Костюм4')
    INSERT INTO Гардероб (ID, Шкафчик) VALUES ('Костюм4', '🎒');

В итоге получаем:

Markdown
Скопировать код
До: [Костюм1, Костюм2, Костюм3, ...]
После: [Костюм1, Костюм2, Костюм3, Костюм4(🎒), ...]

Адаптация к реальным ситуациям

В практической работе INSERT if not exists может встраиваться в крупные операции, например в хранящиеся процедуры или в транзакции, включающие несколько таблиц:

SQL
Скопировать код
CREATE PROCEDURE InsertIfNotExists
    @Колонка1Значение Тип1,
    @Колонка2Значение Тип2
AS
BEGIN
    IF NOT EXISTS (SELECT 1 FROM ВашаТаблица WHERE Колонка1 = @Колонка1Значение)
    BEGIN
        INSERT INTO ВашаТаблица (Колонка1, Колонка2)
        VALUES (@Колонка1Значение, @Колонка2Значение);
    END;
END;

Настройка вашего инструмента при помощи EXCEPT

Если требуется оптимизация производительности, рассмотрите возможность использования EXCEPT для исключения уже существующих записей в процессе вставки:

SQL
Скопировать код
INSERT INTO ВашаТаблица (Колонка1, Колонка2)
SELECT Колонка1, Колонка2
FROM (
    SELECT Значение1, Значение2 
    EXCEPT 
    SELECT Колонка1, Колонка2 FROM ВашаТаблица
) AS Данные

Полезные материалы

  1. Осторожно используйте оператор MERGE в SQL Server
  2. Оператор MERGE в SQL Server 2008
  3. Использование EXISTS и NOT EXISTS в SQL Server для выполнения вставок
  4. Обработка параллельности в SQL Server: использование IF NOT EXISTS в сравнении с проверками в C#