如何避免可能导致DB不匹配的间接引用

时间:2011-01-20 13:51:18

标签: tsql database-design

运行SQL-server 2005并使用简化版本的数据库模型,如下图所示。

该模型工作得很好但我的问题是当我想在Subscriptions和Addresses或Ports之间添加引用时。如果我在Subscriptions.port_id和Ports.id之间创建一个普通的FK,那么可能会喜欢一个引用另一个客户的端口/地址,而不是订阅引用的客户。

我想知道是否可以避免此问题,或者我是否必须处理代码中的问题并且存在数据不一致的风险?

alt text

备注 地址和端口是预先填充的,并且在创建客户之前存在

订阅 一些订阅将连接到一个地址,一些订阅将连接到端口,一些订阅将只与客户建立连接。

3 个答案:

答案 0 :(得分:3)

  

我想知道是否可以避免此问题,或者我是否必须处理代码中的问题并且存在数据不一致的风险?

您的模特违反了3NF

请勿在订阅中存储address_idcustomer_id,因为它们由port_id唯一定义。

相反,只存储port_id并通过联接获取address_idcustomer_id

答案 1 :(得分:1)

1)Quassnoi说什么

2)如果出于某种原因,您确实希望维护表格的当前结构:

ALTER TABLE Addresses ADD CONSTRAINT UQ_Addresses_WithCustomers (Id,Customer_ID)

ALTER TABLE Ports ADD CONSTRAINT UQ_Ports_WithAddresses (Id,Address_ID)

这些将超级密钥添加到这两个表中,以便外键约束可以引用它们

ALTER TABLE Subscriptions ADD
    CONSTRAINT FK_Subscription_Addresses (Address_ID,Customer_ID)
    references Addresses (Id,Customer_ID)

ALTER TABLE Subscriptions ADD
    CONSTRAINT FK_Subscription_Ports (Port_ID,Address_ID)
    references Ports (ID, Address_ID)

这些外键现在强制您匹配address表中与address_id和client_id匹配的行。

而且,大概你还没有这个:

ALTER TABLE Subscriptions ADD
    CONSTRAINT CK_Subscription_EnhancedNUllability CHECK
     (Port_ID is null or Address_ID is not null)

因为否则你可能在subscriptions表中有一个null address_id和一个非null的port_id,并且这是不可检查的(外键约束不适用,因为address_id为null)


Re:备注地址和端口已预先填充并在创建客户之前存在

我为这些创建单独的表,没有可空列,然后引入具有这些Address,Ports和Client表的外键的新表(ClientAddresses,ClientPorts)。然后更改上面的内容,让Subscriptions引用ClientAddresses / Ports表。简而言之,我用可空列留下的唯一表就是订阅表,上面的约束就足够了。所以你有:

CREATE TABLE Addresses (
    AddressID int IDENTITY(1,1) not null,
    Name nchar(10) not null,
    constraint PK_Addresses PRIMARY KEY (AddressID),
    constraint UQ_Address_Names UNIQUE (Name)
)

CREATE TABLE ClientAddresses (
    ClientID int not null,
    AddressID int not null,
    constraint PK_ClientAddresses PRIMARY KEY (AddressID) /*This also prevents the same address being assigned to multiple clients */,
    constraint FK_ClientAddresses_Clients FOREIGN KEY (ClientID) references Clients (ID),
    constraint FK_ClientAddresses_Addresses FOREIGN KEY (AddressID) references Addresses (AddressID),
    constraint UQ_ClientAddresses_WithClients UNIQUE (ClientID,AddressID)
)

UQ_ClientAddresses_WithClients用作订阅的外键关系的目标。

答案 2 :(得分:1)

alt text