2010-05-17 6 views
4

Я собираю таблицу, которая будет использоваться для отправки последующих сообщений на определенные запросы для информации. Запрос отправляется группе людей, и ответы отслеживаются. Если человек не отвечает, может быть отправлено ноль или более последующих действий. Я создал таблицу:Отключить ограничения во время транзакции

FollowupId int primary key, 
RequestId int foreign key (outside this example), 
Follows int foreign key (FollowupId), 
Message varchar 

Если сообщение должно быть первым последующим сообщением, Follows будет null. В противном случае, это идентификатор некоторого другого продолжения. Я также добавил уникальное ограничение на Follows. То есть, не более одного сообщения могут следовать за любым сообщением.

РЕДАКТИРОВАТЬ: Я также должен выделить внешний ключ в соответствии с инструкциями. Он ссылается на FollowupId в этой таблице. Поэтому, если A-> B-> C, просто удаление B делает внешний ключ на C недопустимым. Точно так же невозможно просто обновить C, чтобы следовать за A, потому что B уже следует за A, а уникальное ограничение запрещает дублирование.

Проблема, конечно, в том, что удаление последующих записей затруднено, если за этим сообщением следует другое. Мне кажется, что должно быть возможно отключить проверку ограничений, чтобы можно было удалить среднюю проверку, «переместиться» после последующих действий, а затем снова установить проверку. Есть ли способ отключить ограничение только на время транзакции?

(Кроме того, я знаю о возможной несогласованности данных, возникающих при наличии RequestId в этой таблице. Возможно, было бы лучше иметь Followups [FollowupId, Message], InitialFollowups [FollowupId, RequestId] и AfterFollowups [FollowupId, Follows ]. Я думаю, что это излишне усложняет этот пример.)

ответ

3

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

В вашем случае вам нужно удалить одну строку и изменить другую. Вы должны использовать MERGE, если вы уже находитесь на SQL 2008, что позволяет одновременно удалять и обновлять одну команду.

0

Сначала обновите свои другие значения, а затем сделайте удаление.

Итак, если заказ

A -> B -> C

и вы удаляете B, обновление C следует за А, FollowedUp к C, а затем удалить B.

1

Я обнаружил, что (по крайней мере, на SQL Server) невозможно отключить уникальные ограничения. Можно отключить ограничение внешнего ключа, установить идентификатор удаляемой записи в недопустимый и невозможный идентификатор (например, -1 в моем случае), изменить идентификаторы последующих действий, удалить соответствующую запись и затем возобновить ограничение проверка. Предполагая следующие данные:

FollowId | Запросить | Следующее | Сообщение
1 | 17 | NULL | «Первый»
2 | 17 | 1 | «Второй, удалите этот»
3 | 17 | 3 | "Третий один, но сделать его вторым"

я использовал следующую стратегию:

// начать транзакцию

alter table RequestFollowups NOCHECK CONSTRAINT FK_Follows_FollowId; 
update RequestFollowups set Follows=-1 where FollowupId=2; 
update RequestFollowUps set Follows=1 where FollowupId=3; 
delete from RequestFollowups where FollowupId=2; 
alter table RequestFollowups WITH CHECK CHECK CONSTRAINT FK_Follows_FollowId; 

// совершающие сделки

Смежные вопросы