SQL2005: связать таблицу с несколькими таблицами и сохранить целостность ссылки? - PullRequest
3 голосов
/ 21 августа 2008

Вот упрощение моей базы данных:

Table: Property
Fields: ID, Address

Table: Quote
Fields: ID, PropertyID, BespokeQuoteFields...

Table: Job
Fields: ID, PropertyID, BespokeJobFields...

Затем у нас есть другие таблицы, которые относятся к цитате и Job таблицам индивидуально.

Теперь мне нужно добавить таблицу Message , где пользователи могут записывать оставленные клиентами телефонные сообщения о заданиях и предложениях.

Я мог бы создать две идентичные таблицы ( QuoteMessage и JobMessage ), но это нарушает принцип DRY и кажется грязным.

Я мог бы создать одно Сообщение Таблица:

Table: Message
Fields: ID, RelationID, RelationType, OtherFields...

Но это мешает мне использовать ограничения для обеспечения ссылочной целостности. Я также могу предвидеть, что позже возникнут проблемы со стороной разработки, использующей Linq to SQL.

Есть ли элегантное решение этой проблемы, или мне в конечном итоге придется что-то взломать?

Ожоги

Ответы [ 4 ]

4 голосов
/ 21 августа 2008

Создайте одну таблицу сообщений, содержащую уникальный идентификатор сообщения и различные свойства, которые необходимо сохранить для сообщения.

Table: Message
Fields: Id, TimeReceived, MessageDetails, WhateverElse...

Создание двух таблиц ссылок - QuoteMessage и JobMessage. Они будут содержать только два поля, внешние ключи для цитаты / задания и сообщения.

Table: QuoteMessage
Fields: QuoteId, MessageId

Table: JobMessage
Fields: JobId, MessageId

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

1 голос
/ 21 августа 2008

@ ожоги

Ответ Яна (+1) правильный [см. Примечание] . Использование таблицы «многие ко многим» QUOTEMESSAGE для объединения QUOTE в MESSAGE является наиболее правильной моделью, но оставит потерянные записи MESSAGE.

Это один из тех редких случаев, когда можно использовать триггер. Однако необходимо соблюдать осторожность, чтобы гарантировать, что одна запись MESSAGE не может быть связана с QUOTE и JOB.

create trigger quotemessage_trg
on quotemessage
for delete
as
begin

delete 
from [message] 
where [message].[msg_id] in 
    (select [msg_id] from Deleted);

end

Примечание для Яна, я думаю, что в определении таблицы для JobMessage есть опечатка, где столбцы должны быть JobId, MessageId (?). Я бы отредактировал вашу цитату, но мне понадобится несколько лет, чтобы получить такой уровень репутации!

1 голос
/ 21 августа 2008

О единственном другом способе, который я могу придумать, - это иметь базовую таблицу сообщений с Id и TypeId. Ваши подтаблицы (QuoteMessage и JobMessage) затем ссылаются на базовую таблицу как на MessageId, так и на TypeId, но также имеют CHECK CONSTRAINTS для принудительного применения только соответствующего MessageTypeId.

Table: Message
Fields: Id, MessageTypeId, Text, ...
Primary Key: Id, MessageTypeId
Unique: Id

Table: MessageType
Fields: Id, Name
Values: 1, "Quote" : 2, "Job"

Table: QuoteMessage
Fields: Id, MessageId, MessageTypeId, QuoteId
Constraints: MessageTypeId = 1
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
            QuoteId = Quote.QuoteId

Table: JobMessage
Fields: Id, MessageId, MessageTypeId, JobId
Constraints: MessageTypeId = 2
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
            JobId = Job.QuoteId

Что это дает вам по сравнению с таблицами JobMesssage и QuoteMessage? Он поднимает Сообщение для первоклассного гражданина, так что вы можете читать все Сообщения из одной таблицы. В свою очередь, ваш путь запроса от сообщения к его соответствующей цитате или заданию - еще 1 присоединение. Это зависит от вашего потока приложений, является ли это хорошим компромиссом или нет.

Что касается двух идентичных таблиц, нарушающих СУХОЙ - я бы не стал зацикливаться на этом. В дизайне БД речь идет не о СУХОЙ, а о нормализации. Если две вещи, которые вы моделируете, имеют одинаковые атрибуты (столбцы), но на самом деле разные вещи (таблицы) - тогда разумно иметь несколько таблиц с одинаковыми схемами. Гораздо лучше, чем перебивать разные вещи вместе.

0 голосов
/ 21 августа 2008

Почему бы просто не иметь оба поля QuoteId и JobId в таблице сообщений? Или сообщение должно касаться цитаты или работы, а не обоих?

...