如果我有tblBookInfo(bookId,title等),并且希望它具有Categories列,那么最好的方法是什么?

时间:2018-07-01 01:53:33

标签: sql-server relationship categories jointable

如果我有tblBookInfo(bookId,title等),并且希望它具有Categories列,那么最好的方法是什么?

选项1

类别表将具有与bookId相关的FK,像这样

tblBookInfo
bookId     title
1          test title
2          test title 2
tbl类别
bookId     name
1          Science fiction
1          Mystery
1          Horror
2          Science fiction
2          Mystery

在这种情况下,类别名称将重复很多次而且很丑

选项2

像这样在btlBookInfo中存储一个int数组

tblBookInfo
bookId     title          categories
1          test title     [1,2,3]
2          test title 2   [1,2]

我听说here

并不是将数组存储在列中的最佳做法

选项3

像这样保留类别表

tbl类别
id     name
1      Science finction
2      Mystery
3      Horror

像这样向tblBookInfo添加一个FK

tblBookInfo
bookId     title          categoryId
1          test title     1
2          test title 2   2

最后,添加另一个将这些链接到此类表的表

tblCategoryAdapter
bookId     categoryId
1          1
1          2
1          3
2          1
2          2

现在我不必重复类别名称,但是我不认为这是否正常

1 个答案:

答案 0 :(得分:1)

通过对问题域的透彻了解,检查发现的实体并确保了解这些实体之间的关系来确定如何构建数据库非常简单。

在这里,您有两个实体:Book和Category。看来,您已经从问题域中确定了两个规则:

  1. 一本书可以属于一个或多个类别
  2. 一个类别可以包含1本或更多本图书

以上内容可以简化为“书籍和类别之间存在多对多关系。”

在经典的SQL数据库引擎中,不可能直接在两个表之间实现多对多关系。它必须通过两个原始表中的每一个之间的一对多或0对多关系来实现,该关系与一个新表用于交叉引用原始两个表的行。这些表被称为“交叉引用表”,“关系表”,“联接表”或“交叉表”。

在您的情况下,您似乎需要一个表来将“书籍”与“类别”进行交叉引用,反之亦然。

这可能以图表的形式表示(由于在堆栈溢出中很难绘制,所以有点糟糕):

Book <----- Book_Category -----> Category

Book -1-----M- Book_Category -M-----1- Category

因此,您需要引入Book_Category表(使用您选择的任何名称),该表包含Book表的外键和Category表的外键。

您可以这样做:

tblBookInfo

CREATE TABLE tblBookInfo(
    BookId int not null,
    Name varchar(50) not null,
    CONSTRAINT PK_tblBookInfo PRIMARY KEY CLUSTERED (BookId)
);

tblCategory

CREATE TABLE tblCategory(
    CategoryId int not null,
    Name varchar(50) not null,
    CONSTRAINT PK_tblCategory PRIMARY KEY CLUSTERED (CategoryId)
);

tblBookInfo_Category

CREATE TABLE tblBookInfo_Category(
    BookId int not null FOREIGN KEY REFERENCES tblBook(BookId),
    CategoryId int not null FOREIGN KEY REFERENCES tblCategory(CategoryId)
);