【问题标题】:SQL Foreign key issue with 2 parent tables2个父表的SQL外键问题
【发布时间】:2012-05-01 08:17:31
【问题描述】:

我有 2 张桌子 UserGroup。 我有一个表Attributes shared 由用户和组与列:

  • attributeName
  • AttributeValue
  • ObjectID

ObjectID 指向用户的主键或组的主键。 我添加了一个带有Cascade on Delete 的外部约束,以便在删除用户或组时自动删除属性。

现在的问题是当我为用户插入一个属性时,我有一个外键约束,因为该组不存在。

我应该如何进行?

【问题讨论】:

  • 我认为您应该考虑使用两个属性表。一个用于用户,一个用于组。
  • 或者用父表上的触发器替换外键和约束来捕获删除?
  • 我不会。 FK 的主要目的不是级联删除。它可以确保您不会为不存在的用户/组添加属性。在 UserId 和 GroupId 的 Attributes 中使用相同的字段是一个坏主意。您可以在 Attributes 中使用两列而不是两个表,但正如我所说,我会选择两个表。
  • 是的,Climbage belows 倾向于相同的答案。困扰我的是我复制了相同的表格。事实上,我有 4 个父对象:用户/组/联系人/角色。我将不得不创建 4 个相同的表来存储属性。
  • 我还有一个“链接”表,它将源对象(用户或组)与目标对象(用户或组)链接起来。这张桌子的设计相当简单。这是通用的 IDROW |源ID |目标 ID。当我删除用户或组(源或目标)时,我希望自动删除此链接。至于上面的示例,这个“链接”表是由用户/组/联系人“共享”的……如果我关注你,我将不得不创建十几个相同的表?

标签: sql database database-design


【解决方案1】:

你基本上有3个选择:

  1. 保留您当前的设计,但将Attribute.ObjectID 替换为UserIDGroupID,为它们中的每一个附加一个单独的FK(一个朝向Group,另一个朝向User)并允许其中一个为NULL .您还需要一个 CHECK 约束来确保不是两个都为 NULL。

  2. Attribute 表拆分为UserAttributeGroupAttribute,从而将每个外键分离到自己的表中。

  3. 使用继承,像这样:

解决方案 (1) 高度依赖于您的 DBMS 如何处理 NULL 上的 UNIQUE,并且 (1) 和 (2) 都允许将相同的 AttributeName 用于两个不同的属性,一个用于用户,另一个用于组.

【讨论】:

  • 你能解释一下选项 3 吗?我不明白您是如何将组和用户与对象相关联的,是 1 位父母有 2 个孩子吗?
  • @Suleman No. 用户由Object 中的一行和User 中的一行表示。相反,一个组由Object 中的一行和Group 中的一行表示。
【解决方案2】:

正如您所发现的,您不能将一列作为两个不同表的外键。当用户不存在具有相同 id 的组时,您不能为用户添加属性。而且您当然可以不知道该属性是针对用户还是针对组的。

您还从 cmets 中提到了用户和组之间的 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
)

注意:属性表的使用应该是针对您事先不知道的属性。您所知道的所有属性都应该是实际表中的字段。为客户定义的属性保留属性的使用。

【讨论】:

    【解决方案3】:

    我认为您应该允许此外键字段ObjectId 使用NULL 值,这样您就可以插入任何带有ObjectId = null 且不引用任何用户或组的行。

    为了更好的设计,您应该删除此 ObjectId 列,将新列 AttributeId 添加到两个表 UserGroup

    【讨论】:

      猜你喜欢
      • 2016-09-06
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多