mysql - SQL 多个表之间的多对多关系

标签 mysql sql

我有一个正在尝试在 SQL 上创建的数据库,并且正在尝试将关系连接在一起。共有三个表:superhero、power 和 superheroPower。表 superhero 和 power 是多对多关系,由表 superheroPower 表示。

下面的语法对于表(以及其他所有内容)之间的外键是否正确?另外,这些表在设置方面还有其他建议吗?

CREATE TABLE superhero( id INT NOT NULL AUTO_INCREMENT, 
heroName VARCHAR(255) NOT NULL, 
firstName VARCHAR(255), 
lastName VARCHAR(255), 
firstAppearance DATE, 
gender VARCHAR(255), 
bio TEXT, 
universe VARCHAR(255), 
PRIMARY KEY(id)
) ENGINE=InnoDB;

CREATE TABLE power( 
id INT NOT NULL AUTO_INCREMENT, 
name VARCHAR(255) NOT NULL, 
description TEXT NOT NULL,
PRIMARY KEY(id)
) ENGINE=InnoDB;

CREATE TABLE superheroPower( 
superheroID INT, 
powerID INT, 
PRIMARY KEY(superheroID, powerID), 
FOREIGN KEY(superheroID) REFERENCES superhero(id), 
FOREIGN KEY(powerID) REFERENCES power(id) 
) ENGINE=InnoDB;

最佳答案

是的,那里的一切看起来都不错。但是...

<小时/>

一些注意事项:

我们会为gender 列使用更短的数据类型;我不认为我们需要 255 个字符来表达这一点。 (强制执行的行的最大大小有限制。)如果只有几个值,我们会考虑 ENUM 数据类型。

我们还可能在其中几个列上添加 NOT NULL 约束,例如英雄名、名字、姓氏。我们还可能添加DEFAULT ''。有时,出于某种原因,我们确实需要允许 NULL 值,但我们会尽可能使用 NOT NULL

我对 TEXT 列犹豫不决。使用 TEXT 数据类型没有任何问题,但我只是怀疑这些数据类型可能“隐藏”了一些最好存储在其他列中的信息。

对于外键,我们将按照我们使用的模式为约束分配一个名称,并且还可能添加ON UPDATE CASCADE ON DELETE CASCADE

CONSTRAINT FK_superheroPower_power FOREIGN KEY (powerID) 
  REFERENCES power(id) ON UPDATE CASCADE ON DELETE CASCADE
<小时/>

关于标识符(表名和列名)的注释

我们这样做的方式是,所有表名都是小写的。 (我们有一个 MySQL 选项集,强制所有表名都小写。)我们这样做是为了避免不同操作系统/文件系统(其中一些区分大小写,有些不区分大小写)的不兼容问题。

此外,表名称是单数。表的名称命名了表的一行所代表的内容。我们也不将 _table 作为名称的一部分。

MySQL 中的列名从不区分大小写,但我们也始终使用小写的列名。我们的列名称不使用“驼峰命名法”,我们使用下划线字符作为分隔符,例如power_idpowerIDhero_nameheroName

<小时/>

跟进

我上面的“注释”并不是必须遵守的具体规则;这些只是我们使用的模式。

遵循这些模式并不能保证我们会拥有成功的软件,但它确实对我们有帮助。

为了供您引用,我将展示这些 table 作为我们商店的“初剪”的外观,作为另一种图案的说明;这不是“正确的方式”,这只是我们作为一个团队确定的“一种方式”。

CREATE TABLE superhero
( id               INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'pk'
, hero_name        VARCHAR(255) NOT NULL                COMMENT ''
, first_name       VARCHAR(255) NOT NULL DEFAULT ''     COMMENT ''
, last_name        VARCHAR(255) NOT NULL DEFAULT ''     COMMENT ''
, first_appearance DATE                                 COMMENT 'date superhero first appeared'
, gender           ENUM('female','male','other')        COMMENT 'female,male or other'
, biography_text   TEXT                                 COMMENT ''
, universe         VARCHAR(255)                         COMMENT ''
, PRIMARY KEY(id)
, UNIQUE KEY superhero_UX1 (hero_name) 
) ENGINE=InnoDB;

CREATE TABLE power
( id               INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'pk'
, name             VARCHAR(255) NOT NULL                COMMENT ''  
, description_text TEXT NOT NULL                        COMMENT '' 
, PRIMARY KEY(id)
, UNIQUE KEY power_UX1 (name)
) ENGINE=InnoDB;

CREATE TABLE superheropower
( superhero_id   INT UNSIGNED NOT NULL         COMMENT 'pk, fk ref superhero'
, power_id       INT UNSIGNED NOT NULL         COMMENT 'pk, fk ref power'
, PRIMARY KEY(superhero_id, power_id)
, CONSTRAINT FK_superheropower_superhero 
     FOREIGN KEY(superhero_id) REFERENCES superhero(id)
     ON UPDATE CASCADE ON DELETE CASCADE
, CONSTRAINT FK_superheropower_power
     FOREIGN KEY (power_id) REFERENCES power(id) 
     ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;

关于mysql - SQL 多个表之间的多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53132712/

相关文章:

mysql - 如何获取表中当前行的下一行和上一行

php - 带有 MySQL 查询的空白 HTML 页面

mysql - 获取MYSQL嵌套结果

sql - 从数据子集中选择

sql - 从表变量插入表?

sql - 忽略 hive 查询中具有 NULL 连接列的行

php - laravel Eloquent 关系不起作用

java - 无法从 Java 将文本添加到 mysql 表

java - 从 Canvas 元素查询 MySQL 数据库?

sql - 在多对多关系上使用 ActiveRecord 进行复杂的 Rails 查询