2008-09-25 3 views
1

У меня есть таблица, которая содержит только два столбца - ListID и PersonID. Когда человек сливается с другим в системе, я должен был обновить все ссылки от «источника», чтобы ссылаться на «целевого» человека.Слияние контактов в таблице SQL без создания повторяющихся записей

В идеале, я хотел бы назвать что-то простое, как

UPDATE MailingListSubscription 
SET PersonID = @DestPerson 
WHERE PersonID = @SourcePerson 

Однако, если человек уже существует в этой таблице с той же ListID как исходный человек, дубликат запись будет сделана. Как я могу выполнить это действие без создания дублированных записей? (ListID, PersonID - первичный ключ)

EDIT: используются несколько идентификаторов ListID. Если SourcePerson присваивается ListID 1, 2 и 3, а DestinationPerson назначается ListIDs 3 и 4, то конечный результат должен иметь четыре строки - DestinationPerson, назначенный ListID 1, 2, 3 и 4.

ответ

3
--out with the bad 
DELETE 
FROM MailingListSubscription 
WHERE PersonId = @SourcePerson 
    and ListID in (SELECT ListID FROM MailingListSubscription WHERE PersonID = @DestPerson) 

--update the rest (good) 
UPDATE MailingListSubscription 
SET PersonId = @DestPerson 
WHERE PersonId = @SourcePerson 
+0

Лучшая производительность с использованием вместо – 2008-09-25 19:15:27

+1

Написала оба в анализаторе запросов. Посмотрел планы исполнения. Показаны идентичные планы. «Exists» vs «in» не имеет значения. Индекс на PersonId имеет большое значение. – 2008-09-25 19:43:13

0

Я должен согласиться с Дэвидом Б здесь. Удалите все старые вещи, которых не должно быть, а затем выполните свое обновление.

0

На самом деле, я думаю, вы должны вернуться и пересмотреть свой дизайн базы данных, поскольку вам действительно не должно быть в обстоятельствах, когда вы меняете первичный ключ для записи, как вы предлагаете сделать - это означает, что PersonID столбец на самом деле не является подходящим первичным ключом.

Я предполагаю, что ваш персональный идентификатор открыт для ваших пользователей, они по какой-то причине перенумеровали свою базу данных, и вы снова синхронизируете изменение. Это, как правило, плохая идея, так как она прерывает аудиторские следы и временную согласованность. В этих обстоятельствах обычно лучше использовать свой собственный неизменяемый первичный ключ - обычно идентификатор - и настроить PersonID, который пользователи видят в качестве атрибута этого. Это дополнительная работа, но в долгосрочной перспективе вы получите дополнительную согласованность и надежность.

Хорошее эмпирическое правило - это первичный ключ записи, который не должен подвергаться пользователям, где это возможно, и вы должны делать это только после тщательного рассмотрения. ОК, я признаюсь, что разрастаю это сам во многих случаях, но стоит стремиться к тому, где вы можете :-)

0

Прежде всего, вы должны подписаться на всех списках, на которые подписана SourcePerson, что Destperson еще не подключен. Затем удалите все подписки SourcePersons. Это будет работать с несколькими ListID.

Insert into MailingListSubscription 
(
    ListID, 
    PersonID 
) 
Select 
    ListID, 
    @DestPerson 
From 
    MailingListSubscription as t1 
Where 
    PersonID = @SourcePerson and 
    Not Exists 
    (
     Select * 
     From MailingListSubscription as t2 
     Where 
     PersonID = @DestPerson and 
     t1.ListID = t2.ListID 
    ) 



Delete From MailingListSubscription 
Where 
    PersonID = @SourcePerson 
Смежные вопросы