Database design 将一个表中的多个外键定义为多个表

Database design 将一个表中的多个外键定义为多个表,database-design,foreign-keys,Database Design,Foreign Keys,我有3种型号: 发布: 身份证 头衔 身体 照片: 身份证 文件路径 评论: 身份证 邮政编码 身体 以及相应的数据库表。现在,如果我只想为我的帖子添加注释,我可以简单地添加以下外键:altertable comment add foreign key(post\u id)REFERENCES post(id)。但我想对其他模型(照片、个人资料、视频等)发表评论,并将所有评论保留在one表中。在这种情况下,我如何定义外键(我肯定需要ORM的FKs)?您可以这样做: post:

我有3种型号:

发布

  • 身份证
  • 头衔
  • 身体
照片

  • 身份证
  • 文件路径
评论

  • 身份证
  • 邮政编码
  • 身体
以及相应的数据库表。现在,如果我只想为我的帖子添加注释,我可以简单地添加以下外键:
altertable comment add foreign key(post\u id)REFERENCES post(id)
。但我想对其他模型(照片、个人资料、视频等)发表评论,并将所有评论保留在one表中。在这种情况下,我如何定义外键(我肯定需要ORM的FKs)?

您可以这样做:

 post:
  * post_id (PK)
  * title
  * body

 photo:
  * photo_id (PK)
  * filepath

 comment:
  * comment_id (PK)
  * body

 comment_to_post
  * comment_id (PK) -> FK to comment.comment_id
  * post_id (PK) -> FK to post.post_id

 comment_to_photo
  * comment_id (PK) -> FK to comment.comment_id
  * photo_id (PK) -> FK to photo.photo_id

仍然有可能有属于两个不同项目的评论。如果您认为这是一个问题,我可以尝试改进设计。

在这种情况下,您可以添加一个枚举字段,其中包含“photo”、“profile”。。。它将是外键的第二部分

如果您想知道是否可以将多个外键指向一列,则答案是“不可以”

如果需要,可以使用单独的外键。因此,您可以像这样修改注释表-

 comment:
  * comment_id (PK)
  * PostID (FK to Post.PostID)
  * PhotoID (FK to <Photo>.PhotoID)
  * ProfileID (FK to <Profile>.ProfileID)
  * Body

找到一些常见的帖子、个人资料等——我使用了
Entity
,因为缺少更好的单词,然后是subtype

  • 在该模型中,一个实体可以有多个注释,一个注释只属于一个实体

因为照片评论和帖子评论不一样,所以我会将它们存储在单独的相关表格中。所以我会:

职位:

  • 张贴
  • 头衔
  • 身体
会后通知:

  • 评论
  • 后身份证主体
照片:

  • 类光
  • 文件路径
光通信:

  • 评论
  • 照片编号
  • 身体

使用id作为PK的名称是一种糟糕的做法,这会使报告变得更加困难,并且在复杂查询中更可能无意中连接到错误的表。如果您使用tablenameID并始终为Fks使用相同的名称,那么也更容易查看关系

不,对多个实体发表评论的可能性不是问题。所以我需要N个表来表示N个实体?级联规则在这种情况下有效吗?就是这样,N个表是这种设计的思想。如果DMB支持它们,级联规则肯定会起作用。感谢您的解释。我可能会选择你的方法。关于改进设计,你的意思是什么?我的意思是:想办法让评论#123属于post#456和photo#7891,实际上是不可能的。这是正确的方法。逻辑级别的多:多关系在物理级别实现为关联表。许多表都是标准化数据库的性质;加入不会“花费”任何东西。你能解释一下吗?邮局的桌子是什么样子的。这是不正常的。2.即使你把不规范的问题放在一边,它也不会起作用。当一个FK为真时,其他FK都为假。允许索引字段为空会降低性能。当然,也有标准化的解决方案不存在这样的问题。是的,它不是标准化的。是的,它会起作用。是的,也许在性能方面不是最好的。但是我们在一些限制下工作,比如-1。galymzhan在他的问题中说,他希望所有的评论都在一张表中。2.外键是约束而不是索引。外键字段上没有创建隐式索引。不,它在任何ANSI SQL数据库中都不起作用,请在发布前尝试。您不能有空FK。一、 和其他许多人一样,给OP一个单一的评论表;这不是问题所在。您的答案不规范,因此存在严重的限制和性能问题;这就是问题所在。如果你想继续这个问题,发布一个新问题。我使用SQL server 2008。我试过了。检查我同意,同样,它不是标准化的,这会对性能产生影响。您还没有尝试过它,并且有很多您不理解的地方。无法解决通信网络中的差异;它正在劫持这个线程。如上所述:*如果您想继续,请发布一个新问题**并发布您的DDL。您似乎忽略了以下事实:OP的要求没有在您的回复中提供;你违反了他已经实施/要求的规则。同意重新命名糟糕的列。但是提交明显与请求相反,即规范化评论。这是一种很好的通用设计技术。如果这四个实体有公共列,并且它们可以标准化为超类型,这是一个进步;如果没有,它是一个障碍(例如,没有常见的评论),需要额外的定义(例如,不允许配置文件有评论)。您正在解决一个未发布的问题。我有许多可注释的实体,它们没有公共属性。因此,我的supertable实体将只有EntityId列,我认为这不是一个好的设计。这就是为什么阿尔瓦罗的方法与我更相关。这会起作用,但我们如何限制,帖子的评论将只附在特定的帖子上。并且不能意外地附加到任何其他实体。
Create table Photo
(
PhotoID int,
PhotoDesc varchar(10),
Primary key (PhotoID)
)

Create table Post
(
PostID int,
PostDesc varchar(10),
Primary key (PostID)
)

Create table Profiles
(
ProfileId int,
ProfileDesc varchar(10),
Primary key (ProfileId)
)

Create table Comment  
(
CommentID int,
PhotoID int,
PostID int,
ProfileId int,
body varchar(10),
Primary key (CommentID),
Foreign key (PhotoID) references Photo(PhotoID),
Foreign key (PostID) references Post(PostID),
Foreign key (ProfileId) references Profiles(ProfileId)
)

insert into Photo values (1,'Photo1')
insert into Photo values (2,'Photo2')
insert into Photo values (3,'Photo3')

insert into Post values (11,'Post1')
insert into Post values (12,'Post2')
insert into Post values (13,'Post3')

insert into Profiles values (111,'Profiles1')
insert into Profiles values (112,'Profiles2')
insert into Profiles values (113,'Profiles3')

insert into Comment (CommentID,PhotoID,body) values (21,1,'comment1')
insert into Comment (CommentID,PhotoID,body) values (22,3,'comment2')
insert into Comment (CommentID,PostID,body) values (23,11,'comment3')
insert into Comment (CommentID,PostID,body) values (24,12,'comment4')
insert into Comment (CommentID,ProfileId,body) values (25,112,'comment5')
insert into Comment (CommentID,ProfileId,body) values (26,113,'comment6')

-- to select comments seperately for Photos, profiles and posts
select * from Comment where PhotoID is not null
select * from Comment where ProfileId is not null
select * from Comment where PostID is not null