2008-08-21 63 views
3

這裏是我的數據庫的簡化:SQL2005:將錶鏈接到多個表並保留Ref完整性?

Table: Property 
Fields: ID, Address 

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

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

然後我們有涉及報價工作單獨表等表格。

我現在需要添加一個消息表,用戶可以記錄客戶留下的有關工作和報價的電話留言。

我可以創建兩個相同的表(QuoteMessageJobMessage),而這違反了DRY本金,似乎凌亂。

我可以創建一個消息表:

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

但這阻止我從使用約束強制執行我的引用完整性。我也可以預見它會在後面使用Linq to SQL創建開發方面的問題。

有沒有這個問題的優雅解決方案,或者我最終將不得不一起破解一些東西?

伯恩斯

回答

4

創建一個信息表,包含了獨特的MessageId,你需要存儲的消息的各種屬性。

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

創建兩個鏈接表 - QuoteMessage和JobMessage。這些將只包含兩個字段,即引用/作業和消息的外鍵。

Table: QuoteMessage 
Fields: QuoteId, MessageId 

Table: JobMessage 
Fields: JobId, MessageId 

這樣你只在一個地方定義的消息的數據屬性(使其易於擴展,並在所有郵件查詢),但你也有參照完整性連接行情和喬布斯任何數量的消息。事實上,報價和工作都可以鏈接到相同的消息(我不確定這是否適合您的商業模式,但至少數據模型爲您提供了選項)。

1

關於我能想到的唯一的另一種方式是擁有一個基本消息表,同時包含一個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個加入。它的類型取決於你的應用程序流是否是一個很好的折衷。

至於兩個相同的表違反幹 - 我不會掛在那。在數據庫設計中,它不太關於DRY,更多的是關於規範化。如果你正在建模的兩件事物具有相同的屬性(列),但實際上是不同的事物(表格) - 那麼有多個具有相似模式的表格是合理的。遠遠好於將不同的東西放在一起。

1

@burns

伊恩的回答(+1)是正確的[參閱注]。使用多對多表QUOTEMESSAGE加入QUOTEMESSAGE是最正確的模式,但會留下孤立的MESSAGE記錄。

這是其中之一罕見可以使用觸發器的情況。但是,需要注意確保單個MESSAGE記錄不能同時與QUOTEJOB相關聯。

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一個錯字(?)。我會編輯你的報價,但可能需要我幾年的時間才能獲得這種聲譽!

0

爲什麼在消息表中不只有QuoteId和JobId兩個字段?或者,消息必須是關於報價還是工作,而不是兩者?

相關問題