数据库设计:外键和规范化

时间:2012-08-14 12:44:23

标签: php mysql database database-design

我是数据库设计的新手,所以请耐心等待。我正在使用PHP和MySQL。 我有一个'电影'表,其中包含有关电影的一些细节。这包括类型,有(如果我理解正确)与电影的多对多关系,暗示单个电影可以属于不同类型,单个类型可以属于不同的电影。

从我收集的数据库设计中,将这种关系存储在一个表中并不是一个好主意,因为它会违反First Normal表单或Second Normal表单规则。 我如何设计表格以避免这种情况;我是否必须单独为每个类型创建一个表格?或者<?p>

这引出了我的下一个问题:单独的表需要有外键来识别哪些信息属于哪一行。从理论上讲,如果我有一个唯一的键来识别每部电影,然后我想用它来在一个单独的表中识别一个导演,我将如何在MySQL中创建这种关系?

感谢您的时间 - 如果我做了任何不清楚的事情,请告诉我,我会尽力澄清。

5 个答案:

答案 0 :(得分:4)

  

这包括类型,有(如果我理解正确)很多   与电影有很多关系,暗示一部电影可以归属   不同类型和单一类型可以属于不同的电影。

没错。

  

从我收集的关于数据库设计,存储这种   一张表中的关系不是一个好主意

右。你正在寻找松散的东西。

create table movies (
  movie_id integer primary key
  -- other columns
);

create table genres (
  genre varchar(15) primary key
  -- other columns?
);

create table movie_genres (
  movie_id integer not null,
  genre varchar(15) not null,
  primary key (movie_id, genre),
  foreign key (movie_id) references movies (movie_id),
  foreign key (genre) references genres (genre)
);

对于导演,假设每部电影只有一个导演,你可以使用它来代替上面的电影表

create table movies (
  movie_id integer primary key,
  director_id integer not null,
  foreign key (director_id) references directors (director_id) -- not shown.
  -- other columns
);

答案 1 :(得分:2)

你需要一个表电影,一个表格类型和一个表格Movies_and_Genres。前两个包含可以使用mysql自动增量字段类型创建的唯一主键。第三个表包含这些主键对。

create table movies (id integer not null primary key auto_increment, title ... );
create table genres (id integer not null primary key auto_increment, genre ... );
create table movies_and_genres (id_movie integer not null, id_genre integer not null);

至于导演,这是一个数据建模的问题。如果一部电影可以有多个导演,那么你需要一个导演和一个movies_and_directors表。否则,您只需要电影表中的director表和director列。

答案 2 :(得分:2)

您需要/应该使用junction tables

table 电影:

| id | title | rating |
-----------------------
| 1  | foo   |   5    |
| 2  | bar   |   4    |

table 类型:

| id | name    | 
----------------
| 1  | comedy  |
| 2  | romance |

导演:

| id | name    | 
----------------
| 1  | hello   |
| 2  | world   |

table movie_genre:

| id | movie_id | genre_id |
----------------------------
| 1  |     1    |     1    |
| 2  |     1    |     2    |
| 3  |     2    |     1    |

table movie_director:

| id | movie_id | director_id |
-------------------------------
| 1  |     1    |     1       |
| 2  |     2    |     1       |
| 3  |     2    |     2       |

答案 3 :(得分:2)

你说得对,你需要的是有一张电影表(例如tbl_movies);

pk    id
      name
      ... etc

类型表(例如tbl_genres);

pk    id
      name
      ... etc

和一个链接两者的表格(例如tbl_movie_genres);

fk    id_movies
fk    id_genres

您可以将tbl_movie_geners的pk设置为两个外键,也可以设置独立的pk(例如idtbl_movies中的tbl_genres上面的表格。)

这样你就可以列出每部电影的多种类型,并通过tbl_movie_genres表进行链接;例如:

tbl_movies:
id    name
1     Movie 1
2     Movie 2

tbl_genres:
id    name
1     Horror
2     Action
3     Rom Com

tbl_movie_genres
id_movies    id_genres
1            3
2            1
2            2

会告诉你“电影1”是一部电影,“电影2”是动作恐怖。

答案 4 :(得分:1)

要满足多对多关系,请使用一个连接表来保存电影和流派表的外键:

MOVIE
-----
ID (PK)

GENRE
-----
ID (PK)

MOVIE_GENRE
-----------
MOVIE_ID (FK that references MOVIE(ID))
GENRE_ID (FK that references GENRE(ID))

此处MOVIE表的主键为IDGENRE表的主键为IDMOVIE_GENRE表有两个外键引用:一个到MOVIE.ID,另一个到GENRE.IDMOVIE_GENRE的主键可以是(MOVIE_IDGENRE_ID)的复合键,因为它是唯一的,但您也可以使用合成键。

为了处理导演表和关系,如果它是一对多的关系(许多电影的一个导演),只需在MOVIE表中添加一个外键:

DIRECTOR
--------
ID (PK)

MOVIE
-----
ID (PK)
DIRECTOR_ID (FK TO DIRECTOR(ID))

如果你需要支持另一个多对多关系(许多电影的许多导演),请使用上面的连接表方法。