web-dev-qa-db-fra.com

Code d'erreur: 1215. Impossible d'ajouter une contrainte de clé étrangère - lors de la création de db dans le plan de travail mysql

J'ai créé un modèle pour cette base de données dans le plan de travail mysql, mais maintenant lorsque j'exécute le script pour créer les tables, je reçois: "Code d'erreur: 1215. Impossible d'ajouter une contrainte de clé étrangère".

L'erreur apparaît lorsqu'elle arrive à la table de paiement à la fin du script. Je l'ai regardé depuis un jour, faisant des ajustements ici et là en fonction des solutions que j'ai trouvées en ligne, mais rien ne fonctionne.

Toute aide est fortement appréciée.

-- MySQL Script generated by MySQL Workbench
-- Thu Dec  7 14:01:08 2017
-- Model: New Model    Version: 1.0
-- MySQL Workbench Forward Engineering

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

-- -----------------------------------------------------
-- Schema game_rental
-- -----------------------------------------------------
DROP SCHEMA IF EXISTS `game_rental` ;

-- -----------------------------------------------------
-- Schema game_rental
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `game_rental` ;
USE `game_rental` ;

-- -----------------------------------------------------
-- Table `game_rental`.`platform`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`platform` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`platform` (
  `platform_id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(25) NOT NULL,
  PRIMARY KEY (`platform_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `game_rental`.`member`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`member` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`member` (
  `member_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `first_name` VARCHAR(45) NOT NULL,
  `last_name` VARCHAR(45) NOT NULL,
  `email` VARCHAR(50) NOT NULL,
  PRIMARY KEY (`member_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `game_rental`.`game`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`game` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`game` (
  `game_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(255) NOT NULL,
  `publisher` VARCHAR(45) NOT NULL,
  `rental_duration` TINYINT UNSIGNED NOT NULL DEFAULT 3,
  `rental_rate` DECIMAL(4,2) NOT NULL DEFAULT 5.00,
  `replacement_cost` DECIMAL(5,2) NOT NULL DEFAULT 50.00,
  PRIMARY KEY (`game_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `game_rental`.`game_platform`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`game_platform` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`game_platform` (
  `game_id` SMALLINT UNSIGNED NOT NULL,
  `platform_id` TINYINT UNSIGNED NOT NULL,
  PRIMARY KEY (`game_id`, `platform_id`),
  CONSTRAINT `fk_game_id_plt`
    FOREIGN KEY (`game_id`)
    REFERENCES `game_rental`.`game` (`game_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE,
  CONSTRAINT `fk_platform_id`
    FOREIGN KEY (`platform_id`)
    REFERENCES `game_rental`.`platform` (`platform_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

CREATE INDEX `fk_platform_id` ON `game_rental`.`game_platform` (`platform_id` ASC);


-- -----------------------------------------------------
-- Table `game_rental`.`inventory`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`inventory` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`inventory` (
  `inventory_id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `game_id` SMALLINT UNSIGNED NOT NULL,
  PRIMARY KEY (`inventory_id`),
  CONSTRAINT `fk_game_id_inv`
    FOREIGN KEY (`game_id`)
    REFERENCES `game_rental`.`game` (`game_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

CREATE INDEX `idx_fk_game_id` ON `game_rental`.`inventory` (`game_id` ASC);


-- -----------------------------------------------------
-- Table `game_rental`.`rental`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`rental` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`rental` (
  `rental_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `rental_date` DATETIME NOT NULL,
  `inventory_id` MEDIUMINT UNSIGNED NOT NULL,
  `member_id` SMALLINT UNSIGNED NOT NULL,
  `return_date` DATETIME NULL DEFAULT NULL,
  `staff_id` TINYINT UNSIGNED NOT NULL,
  PRIMARY KEY (`rental_id`),
  CONSTRAINT `fk_inventory_id`
    FOREIGN KEY (`inventory_id`)
    REFERENCES `game_rental`.`inventory` (`inventory_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE,
  CONSTRAINT `fk_member_id`
    FOREIGN KEY (`member_id`)
    REFERENCES `game_rental`.`member` (`member_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

CREATE INDEX `idx_fk_inventory_id` ON `game_rental`.`rental` (`inventory_id` ASC);

CREATE INDEX `idx_fk_member_id_rent` ON `game_rental`.`rental` (`member_id` ASC);


-- -----------------------------------------------------
-- Table `game_rental`.`payment`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `game_rental`.`payment` ;

CREATE TABLE IF NOT EXISTS `game_rental`.`payment` (
  `payment_id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `member_id` SMALLINT UNSIGNED NOT NULL,
  `rental_id` INT UNSIGNED NOT NULL,
  `amount` DECIMAL(5,2) NOT NULL,
  `payment_date` DATETIME NOT NULL,
  PRIMARY KEY (`payment_id`),
  CONSTRAINT `fk_rental_id`
    FOREIGN KEY (`rental_id`)
    REFERENCES `game_rental`.`rental` (`rental_id`)
    ON DELETE SET NULL
    ON UPDATE CASCADE,
  CONSTRAINT `fk_member_id`
    FOREIGN KEY (`member_id`)
    REFERENCES `game_rental`.`member` (`member_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

CREATE INDEX `idx_fk_member_id_pay` ON `game_rental`.`payment` (`member_id` ASC);

CREATE INDEX `fk_rental_id` ON `game_rental`.`payment` (`rental_id` ASC);


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
2
Brian McNamara

Le problème est avec votre première clé étrangère en paiement:

CONSTRAINT `fk_rental_id`
    FOREIGN KEY (`rental_id`)
    REFERENCES `game_rental`.`rental` (`rental_id`)
    ON DELETE SET NULL
    ON UPDATE CASCADE,

Fondamentalement, ce que vous dites, c'est que, quand il y a une SUPPRESSION du game_rental.rental, tous les location_id référencés dans la table de paiement seront définis sur null

Depuis la documentation ( https://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html ):

SET NULL: supprimez ou mettez à jour la ligne de la table parent et définissez la ou les colonnes de clé étrangère de la table enfant sur NULL. Les clauses ON DELETE SET NULL et ON UPDATE SET NULL sont prises en charge.

Si vous spécifiez une action SET NULL, assurez-vous que vous n'avez pas déclaré les colonnes de la table enfant comme NOT NULL.

La dernière ligne devrait tout clarifier, vous avez location_id défini comme NON NUL dans le paiement, donc il y a le problème. Vous devez soit supprimer la restriction NOT NULL dans le rental_id de votre table payment, ou supprimez le "ON DELETE SET NULL ".

Finalement; après cela, vous aurez une autre erreur:

Can't write; duplicate key in table 'payment'

Parce que le nom

CONSTRAINT `fk_member_id`

est utilisé dans game_rental.rental d'abord, vous devrez changer le nom dans la table de paiement pour cette CONTRAINTE et ce sera tout.

2
Mauricio Cacho