Database SQL2005:将一个表链接到多个表并保持引用完整性?
以下是我的数据库的简化: Table: Property Fields: ID, Address Table: Quote Fields: ID, PropertyID, BespokeQuoteFields... Table: Job Fields: ID, PropertyID, BespokeJobFields... 表:财产 字段:ID、地址 表:报价 字段:ID、PropertyID、BespokeQuoteFields。。。 表:工作 字段:ID、PropertyID、BespokeJobFields。。。 然后,我们还有与报价和作业表相关的其他表 我现在需要添加一个Message表,用户可以在其中记录客户关于工作和报价的电话留言 我可以创建两个相同的表(QuoteMessage和JobMessage),但这违反了DRY原则,看起来很混乱 我可以创建一个消息表: Table: Message Fields: ID, RelationID, RelationType, OtherFields... 表:信息 字段:ID、RelationID、RelationType、其他字段。。。 但这阻止了我使用约束来强制我的引用完整性。我还可以预见它在以后使用LINQtoSQL开发方面会产生问题 这个问题是否有一个优雅的解决方案,或者我最终是否要一起解决一些问题Database SQL2005:将一个表链接到多个表并保持引用完整性?,database,sql-server-2005,referential-integrity,Database,Sql Server 2005,Referential Integrity,以下是我的数据库的简化: Table: Property Fields: ID, Address Table: Quote Fields: ID, PropertyID, BespokeQuoteFields... Table: Job Fields: ID, PropertyID, BespokeJobFields... 表:财产 字段:ID、地址 表:报价 字段:ID、PropertyID、BespokeQuoteFields。。。 表:工作 字段:ID、PropertyID、Bespo
Burns创建一个消息表,其中包含一个唯一的消息ID和需要为消息存储的各种属性
Table: Message
Fields: Id, TimeReceived, MessageDetails, WhateverElse...
创建两个链接表-QuoteMessage和JobMessage。这些字段只包含两个字段,分别是报价/作业和消息的外键
Table: QuoteMessage
Fields: QuoteId, MessageId
Table: JobMessage
Fields: JobId, MessageId
通过这种方式,您只在一个位置定义了消息的数据属性(便于扩展和跨所有消息查询),但您还具有将引号和作业链接到任意数量消息的引用完整性。事实上,Quote和Job都可以链接到同一个消息(我不确定这是否适合您的业务模型,但至少数据模型为您提供了选择)。关于我能想到的唯一其他方法是拥有一个同时具有Id和TypeId的基本消息表。然后,您的子表(QuoteMessage和JobMessage)引用MessageId和TypeId上的基表,但它们也具有检查约束,以仅强制执行适当的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
与一张JobMessage和QuoteMessage表相比,这给你带来了什么?它将消息提升为一等公民,以便您可以从单个表中读取所有消息。作为交换,从消息到相关报价或作业的查询路径是1个多连接。这在某种程度上取决于你的应用程序流,这是否是一个好的权衡
至于两张完全相同的桌子,我不会挂断。在DB设计中,更多的是规范化,而不是干法。如果要建模的两个对象具有相同的属性(列),但实际上是不同的对象(表),那么使用类似模式的多个表是合理的。比把不同的东西咀嚼在一起的相反方式要好得多。@burns
伊恩的答案(+1)是正确的[见注]。使用多对多表QUOTEMESSAGE
将QUOTE
连接到MESSAGE
是最正确的模式,但会留下孤立的MESSAGE
记录
这是极少数可以使用触发器的情况之一。但是,需要注意确保单个消息
记录不能同时与报价
和作业
关联
create trigger quotemessage_trg
on quotemessage
for delete
as
begin
delete
from [message]
where [message].[msg_id] in
(select [msg_id] from Deleted);
end
Ian注意,我认为
JobMessage
的表定义中有一个输入错误,其中的列应该是JobId,MessageId
(?)。我会编辑你的报价,但我可能需要几年的时间才能获得这样的声誉 为什么不在消息表中同时包含QuoteId和JobId字段?或者信息必须是关于报价或工作,而不是两者