我有2个表User
和Group
。 我有一个表Attributes
共享由用户和组的列:SQL 2个父表的外键问题
attributeName
。AttributeValue
。ObjectID
。
ObjectID
指向用户的主键或组的主键。 我已经添加了一个外部约束Cascade on Delete
为了删除用户或组时自动删除属性。
现在的问题是,当我插入用户的属性,我有一个外键约束,因为该组不存在。
我该如何继续?
我有2个表User
和Group
。 我有一个表Attributes
共享由用户和组的列:SQL 2个父表的外键问题
attributeName
。AttributeValue
。ObjectID
。ObjectID
指向用户的主键或组的主键。 我已经添加了一个外部约束Cascade on Delete
为了删除用户或组时自动删除属性。
现在的问题是,当我插入用户的属性,我有一个外键约束,因为该组不存在。
我该如何继续?
你已经基本上3个选项:
保持当前的设计,而是采用UserID
和GroupID
更换Attribute.ObjectID
,另附FK他们每个人(一个对Group
,另一个朝向User
),并允许要么是NULL。你还想要一个CHECK约束来确保不是都是NULL。
拆分Attribute
表UserAttribute
和GroupAttribute
,从而分隔每个外键进入自己的表。
使用继承,像这样:
解决方案(1)高度依赖于你的DBMS如何处理UNIQUE null和两(1) (2)允许相同的AttributeName
用于两个不同的属性,一个用于用户,另一个用于组。
我想你应该让NULL
值这个外键字段ObjectId
,这样就可以与ObjectId
= NULL,不是引用任何用户或组插入任何行。
为了更好的设计,您应该删除这个ObjectId
列,将新列AttributeId
添加到User
和Group
两个表中。
正如你发现你不能有一列作为外键到两个不同的表。如果用户不存在具有相同ID的组,则不能为其添加属性。当然,您可以不知道该属性是否适用于用户或组。
从评论你也提到了用户和组之间的m:m关系,所以我会建议如下。
create table [User]
(
UserID int identity primary key,
Name varchar(50) not null
)
go
create table [Group]
(
GroupID int identity primary key,
Name varchar(50) not null
)
go
create table UserGroup
(
UserID int not null references [User](UserID),
GroupID int not null references [Group](GroupID),
primary key (UserID, GroupID)
)
go
create table UserAttribute
(
UserAttributeID int identity primary key,
Name varchar(50) not null,
Value varchar(50) not null,
UserID int not null references [User](UserID) on delete cascade
)
go
create table GroupAttribute
(
GroupAttributeID int identity primary key,
Name varchar(50) not null,
Value varchar(50) not null,
GroupID int not null references [Group](GroupID) on delete cascade
)
注意:属性表的使用应该针对您以前不知道的属性。所有你知道的东西都是属性,应该是实际表中的字段。保留使用客户定义属性的属性。
非常感谢Mikael。 – CloudAnywhere 2012-04-23 20:19:14
我认为你应该考虑两个属性表。一个用于用户,另一个用于组。 – 2012-04-20 21:52:48
或用父表上的触发器替换外键和约束来捕获删除? – CloudAnywhere 2012-04-20 21:57:40
我不会。 FK的主要目的不是级联删除。它确保您不会为不存在的用户/组添加属性。在UserId和GroupId的Attributes中具有相同的字段是一个坏主意。而不是两个表,你可以在属性中有两列,但正如我所说,我会去两个表。 – 2012-04-20 22:08:09