如何避免可能导致数据库中不匹配的间接引用
运行 SQL-server 2005 并拥有一个简化版本的数据库模型,如下图所示。
该模型运行得很好,但我的问题是当我想在订阅和地址或端口之间添加引用时。如果我在 Subscriptions.port_id 和 Ports.id 之间创建一个普通的 FK,则可能会喜欢一个端口/地址,该端口/地址引用了另一个客户,而不是订阅所引用的客户。
我想知道是否可以避免这个问题,或者我是否必须在代码中处理该问题并冒着数据不一致的风险?
注释 地址和端口已预先填充并在创建客户
订阅 之前存在 有些订阅将连接到地址,有些订阅将连接到端口,有些订阅将仅连接到客户。
Running SQL-server 2005 and having a database model, in a simplified version, that looks like the image below.
The model is working pretty well but my problem is when I would like to add a reference between Subscriptions and Addresses or Ports. If I create an ordinary FK between Subscriptions.port_id and Ports.id it will be possible to like to a Port/Addresses that has a reference to another Customer than the one references by the Subscription.
I would like to know if it's possible to avoid this problem or if I'll have to handle the problem in the code and with the risk of inconsistent data?
Notes
The addresses and ports are pre-populate and exists before the Customers are created
Subscriptions
Some subscription will be connected to an Address, some to Ports and some Subscriptions will only have the connection to the Customer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的模型违反了3NF。
不要在订阅中存储
address_id
和customer_id
,因为它们是由port_id
唯一定义的。相反,仅存储
port_id
并通过联接获取address_id
和customer_id
。You model violates 3NF.
Don't store
address_id
andcustomer_id
in subscriptions, since they are uniquely defined byport_id
.Instead, store only
port_id
and getaddress_id
andcustomer_id
through joins.1) Quassnoi 所说的
2) 如果,无论出于何种原因,您确实想要维护表的当前结构:
这些将超级键添加到这两个表中,以便它们可以通过外键约束引用
这些外键现在强制您正在匹配地址表中与address_id 和client_id 都匹配的行。
而且,大概您还没有这个:
因为否则您可能会在订阅表中拥有一个空的address_id和一个非空的port_id,并且这是不可检查的(外键约束将不适用,因为address_id为空)
回复:注释地址和端口是预先填充的,并且在创建客户之前就存在
我会为这些创建单独的表,没有可为空的列,然后引入新表(ClientAddresses、ClientPorts)具有这些地址、端口和客户端表的外键。然后更改上述内容,让订阅引用 ClientAddresses/Ports 表。简而言之,我唯一保留可为空列的表是订阅表,并且上述约束应该足够了。因此,您可以:
将
UQ_ClientAddresses_WithClients
用作订阅中外键关系的目标。1) What Quassnoi said
2) If, for whatever reason, you do want to maintain the current structure of the tables:
These add superkeys to these two tables, so that they can be referenced by foreign key constraints
These foreign keys now enforce that you're matching a row in the addresses table that matches both the address_id and the client_id.
And also, presumably you don't have this yet:
Because otherwise you could have a null address_id and a non-null port_id in the subscriptions table, and that isn't checkable (the foreign key constraints wouldn't apply because address_id is null)
Re: Notes The addresses and ports are pre-populated and exist before the Customers are created
I'd create separate tables for these, with no nullable columns, and then introduce new tables (ClientAddresses, ClientPorts) that have foreign keys to these Address, Ports and Client tables. Then change the above to have Subscriptions reference the ClientAddresses/Ports tables instead. In short, the only table I'd leave with nullable columns would be the subscriptions table, and the above constraints should be sufficient there. So you'd have:
with
UQ_ClientAddresses_WithClients
being used as the target for the foreign key relationship from subscriptions.