我有 2 张桌子User
和Group
. 我有一个由用户和组Attributes
共享的表,其中包含列:
attributeName
.AttributeValue
.ObjectID
.
ObjectID
指向用户的主键或组的主键。我添加了一个外部约束,Cascade on Delete
以便在删除用户或组时自动删除属性。
现在的问题是当我为用户插入一个属性时,我有一个外键约束,因为该组不存在。
我应该如何进行?
我有 2 张桌子User
和Group
. 我有一个由用户和组Attributes
共享的表,其中包含列:
attributeName
.AttributeValue
.ObjectID
.ObjectID
指向用户的主键或组的主键。我添加了一个外部约束,Cascade on Delete
以便在删除用户或组时自动删除属性。
现在的问题是当我为用户插入一个属性时,我有一个外键约束,因为该组不存在。
我应该如何进行?
你基本上有3个选择:
保留您当前的设计,但 Attribute.ObjectID
用UserID
and替换GroupID
,将单独的 FK 附加到它们中的每一个(一个朝向Group
,另一个朝向User
)并允许其中一个为 NULL。您还需要一个 CHECK 约束来确保它们都不为 NULL。
将表拆分Attribute
为UserAttribute
and GroupAttribute
,从而将每个外键分成自己的表。
使用继承,像这样:
解决方案 (1) 高度依赖于您的 DBMS 如何处理 NULL 上的 UNIQUE,并且 (1) 和 (2) 都允许将相同AttributeName
的属性用于两个不同的属性,一个用于用户,另一个用于组。
正如您所发现的,您不能将一列作为两个不同表的外键。当用户不存在具有相同 id 的组时,您不能为用户添加属性。而且您当然可以不知道该属性是针对用户还是针对组的。
从您还提到 am: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
)
注意:属性表的使用应该是针对您事先不知道的属性。您所知道的所有属性都应该是实际表中的字段。为客户定义的属性保留属性的使用。
我认为您应该允许此外NULL
键字段的值ObjectId
,以便您可以插入任何ObjectId
不引用任何用户或组的 = null 行。
为了获得更好的设计,您应该删除此ObjectId
列,AttributeId
在两个表中添加一个新列,User
然后Group
.