SQL Server ignore_dup_key, по-видимому, игнорируется для оператора слияния - PullRequest
3 голосов
/ 10 февраля 2012

SQL Server 2008.

У меня есть несколько кусков кода, работающих вместе, и эффект довольно странный, поэтому я решил поделиться.

У меня есть таблица с электронными письмами - для простоты пустьпредположим, что есть 2 столбца: ID identity (1,1) int email первичного ключа varchar (900)

Также в столбце электронной почты есть уникальный ключ с IGNORE_DUP_KEY = ON.

С другой сторонысторона проблемы - оператор слияния:

merge into dbo.email
using (
     select distinct email t from #t
) p 
ON t = email
when not matched by target then
insert (email) values  (t);

Стоит отметить, что #t - это (в основном для целей этого запроса) таблица из одного столбца с электронной почтой varchar (500).

Что удивительно, так это то, что запрос не удался:

"Нарушение ограничения UNIQUE KEY 'uq_email'. Невозможно вставить дубликат ключа в объект dbo.email"

Однако это работает без нареканий:

insert into dbo.email (email) select email from #t

Хотя я, очевидно, могу обойти проблему (оператор вставки в любом случае быстрее, так что это путь), я понятия не имею, почему оператор MERGE потерпел неудачу.Любые идеи, кто-нибудь?

РЕДАКТИРОВАТЬ: Полный вариант использования: Шаг 1:

create table #temp (
col1 varchar(500),
col2 varchar(500),
col3 varchar(500),
col4 varchar(500),
col5 varchar(500),
email varchar(500),
id int)

Шаг 2:

# temp заполняется из файла CSV для многих целей

Шаг 3:

объединиться в dbo.email, используя (выберите отдельный адрес электронной почты t из #temp) p ON t = адрес электронной почты, если не соответствует цели, затем вставьте (email) значения (t);

Шаг 0 - Создать скрипт для dbo.email:

CREATE TABLE dbo.email (
id int identity(1,1) not null,
email varchar(900) null,
loaddate date default null,
constraint [PK__email__1111] PRIMARY KEY CLUSTERED
(
    id asc
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY,
CONSTRAINT [uq_email] UNIQUE NONCLUSTERED
(
     EMAIL asc
)
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
) ON PRIMARY

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

1 Ответ

7 голосов
/ 10 февраля 2012

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

Попробуйте вместо этого:

merge into dbo.email
using (
     select distinct email t from #t where email is not null
) p 
ON t = email
when not matched by target then
insert (email) values  (t);

Обновление:
Относительно ignore_dup_key Вы должны прочитать раздел примечаний в документации для оператора merge :

Если для IGNORE_DUP_KEY установлено значение ON для любых уникальных индексов в целевой таблице, MERGE игнорирует этот параметр.

Чтобы иметь уникальное ограничение в SQL Server, которое допускает наличие нескольких нулевых значений, вы должны вместо этого добавить уникальный отфильтрованный индекс.

create unique index UX_xx on TableName(ColName) where ColName is not null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...