7

我想知道如何将作者(如果有多个作者)保存在简单的数据库中。

如果一本书有一个作者,一切都很容易。问题是当我想拥有表Books并希望有可能与表Authors进行简单的选择和连接时:

图书

| id  | Title | ISBN | Authors? | 
---------------------------------
|     |       |      |          |
|     |       |      |          |

作者

| id  | Firs Name | Last Name | Short Name | Pseudonym | 
--------------------------------------------------------
|     |           |           |            |           |
|     |           |           |            |           |

我知道我可以使用具有相同 ISBN 和 TITLE 的单独行,但是我想知道如果标题有时非常大(255 长度的 UTF 字符串/varchar/char)是个好主意。

我知道这可能是非常基本的问题,很抱歉我不得不问这个问题:(

4

4 回答 4

9

摆脱. authors_books

书籍和作者之间存在多对多关系:有些书籍有多个作者,有些作者写了不止一本书。而且,书籍有第一、第二和第三作者,依此类推。您无法以某种不可预测的顺序呈现一本书的作者姓名。作者和出版商决定作者顺序,而不是 dbms 程序员。

因此,您需要一个books_authors包含以下列的表格

  book_id
  author_id
  author_ordinal   (a number like 1,2,3 to denote the order of authors)

您可以使用以下查询获取特定书籍的作者列表:

 SELECT isbn, title, author_ordinal, first, last
   FROM books b
   LEFT JOIN books_authors ba ON (b.id = ba.book_id)
   LEFT JOIN authors a ON (ba.author_id = a.id)
  WHERE isbn = '978whatever'
  ORDER BY author_ordinal

role如果您想使您的软件在书目上完整,那么在您的 books_authors 表中放置一个名为的文本字段也是明智的。人们在书籍创作中扮演着不同的角色,例如“作者”、“插画家”、“编辑”、“系列编辑”、“撰稿人”、“序言作者”等等。该role列将让您捕获该信息。

顺便说一句,如果您始终一致地命名您的 id 列,大多数 dbms 逆向工程工具会更快乐。所以你应该使用books.book_id 和authors.author_id 而不仅仅是books.id 和authors.id。

于 2012-11-12T23:31:31.943 回答
7

由于一本书可以有多个作者,并且一个作者可以写不止一本书,我建议在 Books 和 Authors 表之间建立多对多的关系。

添加另一个链接两者的表,如下所示:

图书作者

| 书号 | 作者ID |

BookID 是 Books.id 的外键,AuthorID 是 Authors.id 的外键。

如果您想返回给定书籍的所有作者,您可以执行以下操作:

SELECT Authors.id, Authors.FirstName, Authors.LastName
FROM Authors INNER JOIN BookAuthors ON Authors.id = BookAuthors.AuthorID
WHERE BookAuthors.BookID = '123'
于 2012-11-12T23:26:54.093 回答
3

你有两种真正的可能性:

  • 每本书有许多作者,但每个作者最多只能拥有一本书(极不可能) - 这样,您将在 Author 表中放置一个外键,将该作者链接到该书。您可以有两个这样的作者具有相同的图书 ID,但这意味着您不必复制图书详细信息,或者实际上,除了图书 ID 之外的任何内容
  • 更有可能:每本书有很多作者,每个作者有很多书。这称为“多对多关系”,需要您添加另一个表。

所以,让我们考虑一下:一本书有它的所有细节和一个 ID。每个作者都有许多详细信息和一个 ID。如果您想将作者与一本书相关联,您可以在另一个表中添加一行,比如说“Credits”。

  • 每个作者可以有很多学分,但每个学分是针对一个作者的。
  • 同样,每本书的封面可以有很多学分,但每个学分都只在那本书上。

这样你就有了两个一对多的关系(从作者到学分,从书到学分),并且可以代表你需要的东西而没有任何尴尬的多值。

于 2012-11-12T23:28:24.027 回答
1

您需要另一个名为 的表BookAuthor,您不需要AuthorsBooks 中的列

BookAuthor
------------
BookID
AuthorID

BookID 引用 Books 上的 PK (BookID) 和 AuthorID 引用 Authors 上的 PK (AuthorID)

Select b.Title, CONCAT(a.[First Name], a.[Last Name]) As AuthorName
From Books b
JOIN BookAuthor ba ON b.ID = ba.BookID
JOIN Authors a ON ba.AuthorID = a.ID
于 2012-11-12T23:27:24.787 回答