22

我试图弄清楚这个令人难以置信的东西,他们称之为数据库设计,但没有取得多大成功,所以我将尝试用一个例子来说明我的问题。

我正在使用 MySQL,这是我的问题:

假设我想创建一个数据库来保存我的 DVD 收藏。我有以下信息要包括在内:

  1. 电影片名
  2. 演员
  3. 运行时间
  4. 类型
  5. 描述
  6. 导向器

我想在这些之间建立关系以提高效率,但不知道如何。

这是我对数据库设计的想法:

电影表 => 电影ID、电影标题、运行时间、描述

年表 => 年

流派表 => 流派

导演表 => 导演

演员表 => actor_name

但是,我将如何在这些表之间创建关系?

另外,我为 Films 表创建了一个唯一 ID,主键会自动递增,我是否需要为每个表创建一个唯一 ID?

最后,如果我要通过 PHP 表单将新电影更新到数据库中,我将如何将所有这些数据插入(包括关系和所有?)

感谢您提供的任何帮助,基思

4

10 回答 10

64

您必须区分属性和实体。实体是事物——通常是名词。属性更像是一段描述信息。在数据库行话中,实体 = 表,属性 = 字段/列。

对于某些事情有一个单独的表,让我们以director为例,称为规范化。虽然在某些情况下它可能很好,但在其他情况下可能没有必要(因为通常它会使查询更加复杂 - 你必须加入所有内容 - 而且速度较慢)。

在这种情况下,不需要年份表,因为除了年份本身之外,没有其他关于年份的属性可供您存储。最好将其反规范化并将年份存储在电影表本身中。

另一方面,导演则不同。也许您会想要存储导演的名字、姓氏、出生日期、死亡日期(如果适用)等。您显然不想在每次输入此人的电影时输入导演的出生日期导演,因此为董事设立一个单独的实体是有意义的。

即使您不想存储有关导演的所有这些信息(您只需要他们的名字),为它创建一个单独的表(并使用代理键 - 我将在一秒钟内完成)很有用,因为它防止印刷错误和重复 - 如果您的某人姓名拼写错误或输入不同(第一个、最后一个与最后一个、第一个),那么如果您尝试查找他们导演的其他电影,您将失败。

对表使用代理键(主键)通常是一个好主意。匹配整数比匹配字符串快得多。它还允许您自由更改名称,而不必担心存储在其他表中的外键(ID 保持不变,因此您无需执行任何操作)。


你真的可以把这个设计走得很远,而这一切都只是弄清楚你想要在其中存储什么。

例如,有些电影不是每部电影只有一个导演,而是有多个导演..所以电影和导演之间会有多对多的关系,所以你需要一张桌子,例如:

films_directors => **filmid, directorid**

更进一步,有时导演也是演员,反之亦然。因此,您甚至可以拥有一个人表,而不是导演和演员表,并使用角色表连接该表。角色表将包含各种职位 - 例如,导演、制片人、明星、演员、抓手、编辑……它看起来更像:

films => **filmid**, title, otherstuff...
people => **personid**, name, ....
roles => **roleid**, role name, ....
film_people => **filmid, personid, roleid**
genre => **genreid**, name, ...
film_genre => **genreid, filmid**

在film_people 表中可能还有一个role_details 字段,它可能包含取决于角色的额外信息(例如,演员正在扮演的角色的名称)。

我还将类型显示为多<>多关系,因为一部电影可能有多种类型。如果你不想要这个,那么而不是film_genre 表,电影将只包含一个genreid。

一旦设置好,就很容易查询和查找给定的人所做的一切,或者一个人作为导演所做的一切,或者曾经导演过电影的每个人,或者与特定电影相关的所有人。它可以一直持续下去。

于 2009-01-29T04:38:41.350 回答
21

以下不是实际的 MySQL 代码。似乎您需要的更多是这里的概念开始。所以这里是你的数据库应该是什么样子的模型。

演员表

  • id(主键)
  • 等(您想存储在演员身上的任何其他列)

导演桌

  • ID
  • 等等

流派表

  • ID
  • 姓名
  • 等等

电影桌

  • ID
  • 标题
  • 描述
  • 运行时间
  • 发布日期
  • 导演id——这是一个外键,指的是导演这部电影的导演的id(主键)
  • 流派id——和导演id一样,这是指电影所属流派的id

演员-电影索引表

  • 电影id——这是一个外键,指的是电影的id
  • actor id -- 这是一个外键,指的是电影中一个演员的 id。

对于电影中的每个演员,您将在演员电影索引中添加一行。因此,如果演员 5 和 13(这些演员的主键)出演了电影 4(同样是该电影的主键),那么您的索引中将有两行反映该事实: 一个电影 id = 4,演员 id = 5,另一个电影 id = 4,演员 id = 13。

希望有帮助。

此外,这假设每部电影都只有一位导演。如果您的库中的任何电影有两个导演(例如贫民窟的百万富翁),您需要从电影表中分离出导演 ID,并创建一个导演-电影索引,如上面的演员-电影索引。

于 2009-01-29T04:34:48.083 回答
11

这些是我会使用的表:

films (_id_, title, runningtime, description)
genres (_id_, name)
people (_id_, name, birthdate, etc...)
roles (_roleid_, rolename)
filmgenres (_filmid_, _genreid_)
castandcrew (_filmid_, _roleid_, _personid_)

与其有一张导演和演员桌,不如只有一张人桌。这也可以包括工作人员(如果您想跟踪第二个初级助理 Dolly Grip 是谁)。每部电影可以是任意数量的类型(例如喜剧和恐怖片)。另外,人们可以在每部电影中扮演任意数量的角色——那里有很多演员/导演。

Roles 表不一定表示演员正在扮演的角色,但它可以。如果你想得到细粒度的话,它可能是“导演”、“制片人”、“演员”……甚至是“卢克天行者”……我相信 IMDB 会这样做。

希望上面字段的名称应该暗示外键,并且我已经放置_underscores_了我要使用的主键。

于 2009-01-29T04:33:49.427 回答
4

您的电影表还需要指向流派、导演和演员表的链接。由于演员至少是多对多的(一部电影会列出不止一个演员,一个演员会出现在不止一部电影中),你需要一个表格来链接它们。

Films Table => filmid, filmtitle, runningtime, description, genreid, directorid
Genre Table => genreid, genre
Director Table => directorid, director
Actors Table => actorid,actor_name
FilmActor link table => actorid, filmid (with a record linking each actor to each film)

任何可能多对多的表都需要一个链接表。

于 2009-01-29T04:30:57.937 回答
4

我已经为 Films 表创建了一个唯一 ID,主键会自动递增,我是否需要为每个表创建一个唯一 ID?

是的,每个表都必须有一个唯一的 ID。但是,这不一定是主要的自动递增键 - 它是使该特定实例唯一的任何因素。例如,对于电影,我认为通常是标题 + 发行年份 - 尽管您想与电影爱好者(领域专家)核实以确保这一点。自动增量是一种后备 - 基本上,当你真的没有其他东西可以唯一化时。

您可以使用自动增量键以便在连接等中使用,但无论如何您都应该对唯一性字段有唯一性约束。

至于实际设计,我建议如下:

Films => Primary Key(filmid), Unique Constraint(filmtitle, year), 
         runningtime, description, 
         Foreign Key(Genre), Foreign Key(DirectorId)

Genre Table => Primary Key(Genre)

Director Table => Primary Key(DirectorId), DirectorName

Actors Table => Primary Key(ActorId), ActorName

Films_Actors => Primary Key(Foreign Key(ActorId), Foreign Key(FilmId))

对于插入,坦率地说,它是一个 PITA。您需要以相反的顺序插入(这是自动增量键可以是更大的 PITA 的地方 - 如果您可以将出生日期或其他内容添加到 Actors 和 Director 表中,那么唯一约束可以使其更容易)。

因此,您将插入 Actor(s)、Director、Film,然后是 Films_Actors。理想情况下,所有这些都在一个事务中。另外,我假设 Genre 已经填写,并且是一个选择列表 - 所以不需要插入它。

于 2009-01-29T04:34:12.920 回答
4

您可以在此处下载 Imdb 架构。

于 2014-03-12T05:17:47.090 回答
2

我知道您的问题已经得到解答,但是我想指出您:
http ://www.imdb.com/interfaces

IMDB 提供其数据库的纯文本文件(减去主键)。一旦开始,您可能会发现这对填充您的数据库很有用,或者您可以在您的程序/网站中使用它来允许您简单地搜索电影标题以添加到您的“DVD Collection”中,并获得其余信息从这些中拉出来。

于 2009-01-29T06:06:42.343 回答
2

有时演员是导演,反之亦然,也许你想要一个“人”表?

于 2009-01-29T08:30:50.463 回答
1

您实际上并不需要 YearTable,您所需要的只是电影表中的genre_id、director_id 和actor_id 列。

此外,您的流派、导演和演员表需要它们自己的唯一 ID。

编辑:当然,这是假设每部电影只有一种类型、导演和演员。情况可能并非如此。

要让许多演员属于许多电影,您将需要一个单独的关系表。你可以称它为“moviesActors”(或actorsMovies),每一行都会有一个actor_id 和一个movie_id 来表示这个演员这部电影中。

于 2009-01-29T04:23:48.933 回答
0

每个表都应该有一个唯一的主键。

您应该阅读数据库规范化

年表可能是不必要的。

例如,如果是发行年份,则可以将年份存储在电影中。

如果一部电影有多个导演,那么您将有一个单独的表,其中包含电影表和导演表的主键。对于任何多对一或多对多的外键约束也是如此。特别是,我相信这将适用于演员。

于 2009-01-29T04:24:55.530 回答