在三个表之间建立关系的正确方法

时间:2016-12-08 20:16:33

标签: mysql sql database

我正在建立一个图书馆数据库,我被困在一个特定的事情上。

我有三个表:BookCopyBookLoanMembers。我不清楚如何建立它们之间的关系,所以一个成员可以借一本书(或书籍),所有这些都可以在我的数据库中正确反映出来。

我的想法是拥有两个多对多表格,因此我添加了BoakLoansMembersBookCopiesBookLoans。我不确定这是否正确,即使是这样,我也不知道如何划分如此多的表格。

所以,现在我想知道在这种情况下最好的做法是什么?为什么?

enter image description here

2 个答案:

答案 0 :(得分:3)

我猜你的BookCopy是因为有Y本书的X副本,并且在这个意义上是#34;书籍"没有贷款,"副本"他们是,对吧?

我认为最好的行动方案可能是认识BookLoan表应该是多对多表。副本一次借给会员,然后返回。 BookLoad应该有副本和成员的ID,以及借出的日期(就像你现在一样,虽然它应该是一个日期时间字段而不是varchar一个)&返回日期(如借出日期,它应该是日期时间,但也应该可以为空,以表示未复制的副本)。您还应该保留贷款的唯一(可能是自动递增)ID,因为成员很可能会多次签出同一份副本。

我猜你也许是最初概念化"贷款"类似于销售交易,可以工作;但是你想要一个loanCopies表,并且不希望贷款上有dateReturned,因为不同的副本可以独立返回。

编辑(其他观察):

  • isAvailable可能是多余的,如果它只是基于是否签出了副本(如果你想保留这本书的流通,那么它可能是合适的)
  • 根据维基百科,ISBN最多为13个字符(在某些情况下,char van比varchar更有效)
  • 您可能需要考虑副本可以引用的语言表,而不是使用字符串类型字段。

编辑(re:isAvailable): 如果您只是需要找到未借出的副本,那么您只需要这样的简单查询。

SELECT * 
FROM BookCopy 
WHERE idBookCopy NOT IN (
  SELECT idBookCopy
  FROM BookLoan
  WHERE dateReturned IS NULL
);

子查询获取借出的副本列表,NOT IN确保结果中的副本不在该列表中。

如果您想阻止某个副本被借出(损坏,破坏等......)isAvailable"标记"可能是添加此类功能的简单方法;只需将AND isAvailable = 1添加到外部查询的WHERE条件中。

答案 1 :(得分:2)

您可以在Members和BookCopy之间建立m:m关系,并使用BookLoan Table作为交叉连接表。所以你基本上只需要将表Members和Bookcopy中的引用添加到Table BookLoan

  BookLoan
  ---------------
  idBookLoan 
  dateLoaned
  dateReturned

  idBookCopy  FK -- add these two
  idMember    FK

还考虑将idBookCopy,idMember和dateLoaned作为BookLoan表的主键