SQL Many-to-Many Relationship Between Multiple Tab

2020-04-18 05:32发布

I have a database I'm trying to create on SQL and I am trying to connect the relationships together. There are three tables: superhero, power, and superheroPower. The tables superhero and power is a many to many relationship which is represented by the table 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;

标签: mysql sql
3条回答
仙女界的扛把子
2楼-- · 2020-04-18 06:17

Edit[1]: This is a version of SQL code on how I would do it!!

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. I have never used the Auto_increment before in my sql tables, so for me that is something new I just learned from you

查看更多
对你真心纯属浪费
3楼-- · 2020-04-18 06:21

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

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;
查看更多
▲ chillily
4楼-- · 2020-04-18 06:31

Yes, everything there looks okay. But...


A few notes:

We'd use a shorter datatype for the gender column; I don't see that we'd need 255 characters to express that. (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.

We'd also likely add NOT NULL constraints on several of those columns, such as heroname, firstname, lastname. We'd also likely add DEFAULT ''. Sometimes, we really do need to allow NULL values for some reason, but we use NOT NULL wherever we can.

I'm hesitant about the TEXT columns. 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.

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

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).

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.

Column names in MySQL are never case sensitive, but we always use lower case for the column names as well. We don't "camelCase" our column names, we use underscore character as separators, e.g. power_id vs. powerID, hero_name vs. heroName.


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;
查看更多
登录 后发表回答