Как проверить наличие кластеризованного уникального ключа при вставке в таблицу SQL

#sql #sql-server

#sql #sql-сервер

Вопрос:

Я пытаюсь вставить строки из другой таблицы базы данных в новую таблицу базы данных, получая приведенную ниже ошибку, если в запросе нет условия where.

Нарушение ограничения УНИКАЛЬНОГО КЛЮЧА ‘NK_LkupxViolations’. Не удается вставить дубликат ключа в объект ‘dbo.LkupxViolation’. Значение повторяющегося ключа равно (00000000-0000-0000-0000-000000000000, (не указано)).

Затем я написал приведенный ниже запрос, добавив, какие условия он выполнял, но он не вставлял ожидаемое количество строк.

 IF EXISTS(SELECT 1 FROM sys.tables WHERE name = 'LkupxViolation')
BEGIN
   INSERT INTO dbo.[LkupxViolation] SELECT * FROM  [DMO_DB].[dbo].[LkupxViolation] where CGRootId not in (select CGRootId from dbo.[LkupxViolation])
   and Name not in (select name from dbo.[LkupxViolation])
END
ELSE 
PRINT 'LkupxViolation table does not exist'
 

Уникальный ключ в таблице создается как:

 CONSTRAINT [NK_LkupxViolations] UNIQUE CLUSTERED
(
    [CGRootId] ASC,
    [Name] ASC
)
 

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

1. Какую базу данных вы используете? Опубликованный вами код не похож на Oracle (хотя вы отметили вопрос как «Oracle11g»).

2. @Littlefoot SQL server

3. Очевидно, что другая БД не имеет уникального ключа для cgrootid / name, если он имеет несколько одинаковых значений. Либо отфильтруйте их с помощью предложения Where, создайте неуникальный индекс или удалите ключ. Мы не можем сказать вам, что делать, потому что мы ничего не знаем о ваших бизнес-потребностях в этих данных

4. Проверьте @@ROWCOUNT в следующей строке, смотрите Здесь рекомендации для UPSERTs

Ответ №1:

Попробуйте использовать NOT EXISTS :

 INSERT INTO dbo.[LkupxViolation]
    SELECT *
    FROM  [DMO_DB].[dbo].[LkupxViolation] remove_l
    WHERE NOT EXISTS (SELECT 1
                      FROM dbo.[LkupxViolation] local_l
                      WHERE local_l.Name = remote_l.Name AND
                            local_l.CGRootId = remote_l.CGRootId
                     );
 

При этом проверяется наличие обоих значений в одной строке. Кроме того, NOT IN это небезопасно NULL . Если какие-либо значения, сгенерированные подзапросом, являются NULL , то все строки отфильтровываются.