【问题标题】:MySQL schema design: one table with type column VS multiple tablesMySQL 架构设计:一张表,类型为列 VS 多张表
【发布时间】:2018-08-04 13:19:48
【问题描述】:

我正在制作一个关于电影的网站,我想在电影和演员(导演、作家和演员)之间建立关系,我有两种可能实现这一点,第一种是创建一个表格每个演员:

CREATE TABLE director(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));  
CREATE TABLE writer(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));  
CREATE TABLE actor(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));

并在每个表和电影表之间建立多对多关系。
第二种可能性是为演员表创建一个类型列,该类型列可以引用导演、作家或演员,并在该表和电影表之间建立多对多关系..

CREATE TABLE cast(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), type varchar(10));

注意:对于演员,自动生成的表会有一些额外的列:character_name、role...
那么哪种可能性更适合这种情况呢?

【问题讨论】:

  • 我会使用第二种方法,更容易管理,添加新类型和更少的表来搜索查找数据。
  • 添加到@Clint 的评论。我还将创建一个类型表cast_type 并在转换表中使用cast_type_id 列...搜索 int 比 varchar 快得多,特别是当转换表很大时。而且 int 数据类型使表数据和索引大小更小也使搜索更快...此外类型表不会变得那么大..

标签: mysql sql


【解决方案1】:

这两种方法都忽略了演员、导演或作家或……(通常)是一个人。那是实际的实体。一个人在电影中的角色(演员、作家……)实际上是一种关系属性。

在这两种方法中都会有冗余。如果某人在一部电影中有多个角色,例如导演和表演(想想希区柯克的客串),那个人会有两张唱片。在第一种方法中,这些分布在两个表中,在第二种方法中分布在一个表中。一个人的属性,如姓名等,将被存储两次,并且可能相互矛盾,或者需要在两个地方进行更改,如果它们发生变化等。

所以我建议第三种方法:为人们创建一个表格,用于存储一个人可以拥有的所有属性(姓名、...)。并有一个表格将人们与电影联系起来,同时还表明一个人在电影中的角色(演员、导演……)。

为角色设置一个表格也可能不是一个坏主意。

例如:

CREATE TABLE people
             (id integer AUTO_INCREMENT,
              name varchar(50),
              PRIMARY KEY (id));

CREATE TABLE roles
             (id integer AUTO_INCREMENT,
              name varchar(10),
              PRIMARY KEY (id));

CREATE TABLE movies_people
             (movie integer,
              person integer,
              role integer,
              PRIMARY KEY (movie,
                           person,
                           role),
              FOREIGN KEY (movie)
                          REFERENCES movies
                                     (id)
                          ON DELETE CASCADE,
              FOREIGN KEY (person)
                          REFERENCES people
                                     (id),
              FOREIGN KEY (role)
                          REFERENCES roles
                                     (id));

【讨论】:

    【解决方案2】:

    我会采用第二种方法。它甚至符合标准的 SQL 规则。

    如果您的演员类型(导演、编剧等)还有一些附加属性(列),您可以进行一些修改。在这种情况下,建议将它们作为主表的子表。

    在您的情况下,主表将是“演员”。它将有 ID 和其他列。其他表将被创建并对应于不同的演员表,如表:“导演”,“作家”,......然后在每个子表之间与主“演员表”进行 1-1 关系。该关系在子表上是强制性的(这意味着例如“导演”在创建时必须与“演员”有关系)。在关系意义上,“导演”的外键也是它的主键,它暗示着“演员”的主键。

    推荐这种方法,因为您不仅可以为不同的演员添加额外的列,还可以添加其他关系,以防您以后想扩展数据库。您还可以添加“演员表”的其他子表,而无需更改与“电影”表相关的结构。

    【讨论】:

    • @RaymondNijland 我建议的方法是可扩展的和灵活的扩展。如果他只想保留演员类型并且知道将来他不需要为每种类型添加额外的唯一列,那么他当然不需要每个单独的表。
    • 我知道..我在“我会采用第二种方法。它甚至对应于标准 SQL 规则。”..“标准 SQL”意味着 ANSI SQL 具有类型功能表和超级/子表或更好的表继承(en.wikipedia.org/wiki/Structured_type),这也很有意义。在 MySQL 中,您不能按照 ANSI SQL 1999 的原因执行此操作,但可以对其进行模拟。
    【解决方案3】:

    第二种方法似乎比第一种更干净。无需维护 3 个不同的表,您只需在一列中获取 type

    此外,您可以使用 bit(0=director, 1=writer, 2=actor) 代替 varchar(10) 来存储 type

    【讨论】:

    • 我建议避免使用数据类型 BIT... MySQL 支持 BIT 数据类型,但仅作为 TINYINT(1) 的同义词。在 MySQL 版本 5.0.3 中,本机 BIT 数据类型。这种类型的行为与 TINYINT 非常不同...数据似乎存储为 BINARY 值,尽管文档将其列为“数字类型”,因此在某些情况下查询可能会很棘手
    猜你喜欢
    • 2012-04-04
    • 1970-01-01
    • 2011-07-28
    • 2012-12-15
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 2014-04-29
    • 2013-03-05
    相关资源
    最近更新 更多