简体   繁体   English

SQL多表多对多关系

[英]SQL Many-to-Many Relationship Between Multiple Tables

I have a database I'm trying to create on SQL and I am trying to connect the relationships together.我有一个我正在尝试在 SQL 上创建的数据库,我正在尝试将这些关系连接在一起。 There are three tables: superhero, power, and superheroPower.共有三个表:superhero、power 和 superheroPower。 The tables superhero and power is a many to many relationship which is represented by the table superheroPower.表 superhero 和 power 是多对多的关系,由表 superheroPower 表示。

Is the syntax below correct for foreign keys between tables (and everything else)?下面的语法对于表(以及其他所有内容)之间的外键是否正确? Also, is there any other recommendations on these tables in terms of their setup?另外,就这些表的设置而言,还有其他建议吗?

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;

Yes, everything there looks okay.是的,那里的一切看起来都不错。 But...但...


A few notes:一些注意事项:

We'd use a shorter datatype for the gender column;我们将为gender列使用较短的数据类型; I don't see that we'd need 255 characters to express that.我不认为我们需要 255 个字符来表达这一点。 (There is a limit on the maximum size of a row which is enforced.) If there only a few values for that, we'd consider ENUM datatype. (强制执行的行的最大大小有限制。)如果只有几个值,我们会考虑ENUM数据类型。

We'd also likely add NOT NULL constraints on several of those columns, such as heroname, firstname, lastname.我们还可能在其中几个列上添加NOT NULL约束,例如 heroname、firstname、lastname。 We'd also likely add DEFAULT '' .我们也可能添加DEFAULT '' Sometimes, we really do need to allow NULL values for some reason, but we use NOT NULL wherever we can.有时,出于某种原因,我们确实需要允许 NULL 值,但我们会尽可能使用NOT NULL

I'm hesitant about the TEXT columns.我对TEXT列犹豫不决。 There's nothing wrong with using TEXT datatype, but I'm just suspicious that those may be "hiding" some information that might better be stored in additional columns.使用TEXT数据类型没有任何问题,但我只是怀疑那些可能“隐藏”了一些可能更好地存储在其他列中的信息。

For the foreign keys, we'd assign a name to the constraints, following the pattern we use, and also likely add ON UPDATE CASCADE ON DELETE CASCADE对于外键,我们会按照我们使用的模式为约束分配一个名称,还可能添加ON UPDATE CASCADE ON DELETE CASCADE

CONSTRAINT FK_superheroPower_power FOREIGN KEY (powerID) 
  REFERENCES power(id) ON UPDATE CASCADE ON DELETE CASCADE

A note about identifiers (table names and column names)关于标识符(表名和列名)的说明

The way we do it, all table name are lower case .我们这样做的方式,所有表名都是小写的 (We have a MySQL option set that forces all table names to lower case.) We do this to avoid incompatibility issues for different operating systems/filesystems (some of which are case sensitive, and some are not). (我们有一个 MySQL 选项集,强制所有表名都为小写。)我们这样做是为了避免不同操作系统/文件系统(其中一些区分大小写,有些不区分大小写)的不兼容问题。

Also, table names are singular .此外,表名是单数 The name of the table names what one row of the table represents.表的名称命名表的一行所代表的内容。 We also don't include _table as part of the name.我们也不包括_table作为名称的一部分。

Column names in MySQL are never case sensitive, but we always use lower case for the column names as well. MySQL 中的列名从不区分大小写,但我们也总是使用小写的列名。 We don't "camelCase" our column names, we use underscore character as separators, eg power_id vs. powerID , hero_name vs. heroName .我们不“驼峰式”我们的列名,我们使用下划线字符作为分隔符,例如power_idpowerIDhero_nameheroName


FOLLOWUP跟进

My "notes" above aren't specific rules that must be followed;我上面的“注释”并不是必须遵守的特定规则; those are just patterns we use.这些只是我们使用的模式。

Following these patterns does not guarantee that we'll have a successful software, but it does help us.遵循这些模式并不能保证我们会有一个成功的软件,但它确实对我们有帮助。

For your reference, I'll show how these tables would look as a "first cut" from our shop, as an illustration of another pattern;为了您的参考,我将展示这些桌子如何看起来像我们店里的“第一次剪裁”,作为另一种模式的说明; this is not "the right way", it's just "a way" that we've settled on as a team.不是“正确的方式”,这只是我们作为一个团队确定的“方式”。

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;

Edit[1]: This is a version of SQL code on how I would do it!!编辑 [1]:这是关于我将如何做的 SQL 代码版本!!

CREATE TABLE superhero
( 
Superheo_id INT NOT NULL AUTO_INCREMENT, 
heroName VARCHAR(255) NOT NULL, 
firstName VARCHAR(255)NULL,
lastName VARCHAR(255)NULL, 
firstAppearance DATE NULL, 
gender VARCHAR(255) NULL, 
bio TEXT NULL, 
universe VARCHAR(255) NULL, 
CONSTRAINT SUPERHERO_PK PRIMARY KEY(SUPERHERO_id)
);

CREATE TABLE power
( 
POWER_id INT NOT NULL AUTO_INCREMENT, 
name VARCHAR(255) NOT NULL, 
description TEXT NOT NULL,
CONSTRAINT POWER_PK PRIMARY KEY(POWER_id)
);

CREATE TABLE superheroPower
( 
superheroID INT DEFAULT(0) NOT NULL, 
powerID INT DEFAULT(0) NOT NULL, 
CONSTRAINT SUPERHEROPOWERS_SUPERHERO_FK FOREIGN KEY(superheroID) REFERENCES superhero(id), 
CONSTRAINT SUPERHEROPOWERS_POWERS_FK FOREIGN KEY(powerID) REFERENCES power(id) 
);

edit[2]:You are able to change null to not null and vise versa depending on if you want a user to move past with out installing the other information.编辑 [2]:您可以将null更改为非 null ,反之亦然,具体取决于您是否希望用户在不安装其他信息的情况下移动过去。 I have never used the Auto_increment before in my sql tables, so for me that is something new I just learned from you我以前从未在我的 sql 表中使用过 Auto_increment,所以对我来说这是我刚刚从你那里学到的新东西

Your design seems on the right track, this is the tables i would have gone with - adding some Indexes for the fields its likely that you will search for and adding the actions needed for the CONSTRAINT keys您的设计似乎走在正确的轨道上,这是我会使用的表 - 为字段添加一些索引,您可能会搜索并添加 CONSTRAINT 键所需的操作

CREATE TABLE `_superhero` (
  `id` int(11) NOT NULL auto_increment,
  `heroName` varchar(255) NOT NULL,
  `firstName` varchar(255) default NULL,
  `lastName` varchar(255) default NULL,
  `firstAppearance` date default NULL,
  `gender` enum('Other','Female','Male') default NULL,
  `bio` text,
  `universe` varchar(255) default NULL,
  PRIMARY KEY  (`id`),
  KEY `indxHname` (`heroName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `_power` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `description` text NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `indx4` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `_superheropower` (
  `superheroID` int(11) NOT NULL default '0',
  `powerID` int(11) NOT NULL default '0',
  PRIMARY KEY  (`superheroID`,`powerID`),
  KEY `indx1` (`superheroID`),
  KEY `indx2` (`powerID`),
  CONSTRAINT `fk2` FOREIGN KEY (`powerID`) REFERENCES `_power` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
  CONSTRAINT `fk1` FOREIGN KEY (`superheroID`) REFERENCES `_superhero` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM