2

这是我的朋友在接受亚马逊电话采访时被问到的一个问题。设计一个关系数据库来记录书籍,其中一本书可以有多个作者,一个作者可以出版多本书。他被要求设计关系(表格)和每个属性的类型(文本、字符串等)。问题是他们还希望能够同时搜索作者姓名和书名。我知道这样的事情不会很有效:

Table Autor 
AutorID AuthorName booksIDs(Text) Example:15, Morris Mano:11,56,234

Table Book
BookID Booktitle AuthorsID(Text) Example: 11:Computer Architecture: 15,34,88 

对于这些属性,还有什么其他类型比 Text 更适合使用?

4

3 回答 3

2

我会这样做:

Author (AuthorId, AuthorName, etc.)
    PK: AuthorId

Book (BookId, BookName, ISBN, Edition, etc)
    PK: BookId

AuthorBooks (AuthorId, BookId)
    PK: (AuthorId, BookId)
    FK: AuthorId from Author, BookId from Book (thanks to Justin's answer for reminding to add this)
    Another index on BookId to facilitate quick search by BookId.
    Note that the PK index can be used to search on AuthorId.

添加新书:

  1. 插入作者
  2. 插入书本
  3. 插入 AuthorBook

按作者姓名搜索(假设作者姓名不唯一):

SELECT ab.*, b.*
FROM   AuthorBook ab, author a
WHERE  ab.AuthorId IN (SELECT AuthorId
                       FROM   Author 
                       WHERE  AuthorName = ?)

同样用于按书名搜索...

于 2013-10-03T23:45:19.987 回答
2

基本的第三范式是这样的,它使用了一个交集表。在关系表中存储逗号分隔值总是一个错误。

CREATE TABLE author (
  authorID integer primary key,
  authorName varchar2(100)
);

CREATE TABLE book (
  bookID integer primary key,
  bookTitle varchar2(100)
);

CREATE TABLE author_book (
  authorID integer,
  bookID   integer,
  constraint pk_author_book primary key( authorID, bookID )
);

现在,实际上,您几乎可以肯定将作者姓名分解为名字、姓氏等,以便于搜索。如果您使用 Oracle,您可能会创建 Oracle Text 索引以便于搜索。如果您是亚马逊,您可能希望创建一些辅助表以方便在不同表中的属性之间进行搜索。

于 2013-10-03T23:42:09.107 回答
1

您应该使用关系表将作者与书籍联系起来,而不是在每个表中放置一个 ID 列表。

CREATE TABLE author_book (
    author_id INT,
    book_id INT,
    UNIQUE KEY (author_id, book_id)
);

要获取作者的书籍或书籍的作者,请使用 3-way join,例如

SELECT BookTitle
FROM Book b
JOIN author_book ab ON b.BooKID = ab.book_id
JOIN Author a ON a.AuthorID = ab.author_id
WHERE AuthorName = 'John Smith';
于 2013-10-03T23:42:46.390 回答