我有一个名为“vehicles”的超类表。我还有三个子类型表,称为“飞机”,“汽车”和“自行车”,这些子类型表中只有一个必须链接到车辆超类型表(换句话说,必须使用车辆主键ID作为主键ID)。
如何对其进行建模以强制执行此行为?
编辑Mike Brant推荐的模式。
-- MySQL Script generated by MySQL Workbench
-- 05/25/16 09:20:17
-- Model: New Model Version: 1.0
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 mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`vehicle_types`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`vehicle_types` (
`type` CHAR(8) NOT NULL,
PRIMARY KEY (`type`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`vehicles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`vehicles` (
`idvehicles` INT NOT NULL AUTO_INCREMENT,
`type` CHAR(8) NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`idvehicles`),
INDEX `fk_vehicles_vehicle_types_idx` (`type` ASC),
CONSTRAINT `fk_vehicles_vehicle_types`
FOREIGN KEY (`type`)
REFERENCES `mydb`.`vehicle_types` (`type`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`airplanes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`airplanes` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_airplanes` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_airplanes_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`automobiles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`automobiles` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_automobiles` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_automobiles_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`bicycles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`bicycles` (
`vehicles_idvehicles` INT NOT NULL,
`data_for_bicycles` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_bicycles_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`)
REFERENCES `mydb`.`vehicles` (`idvehicles`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
答案 0 :(得分:0)
我认为插入车辆和任何其他子类型应该同时进行。因此,您可以获取车辆ID并将其作为新的子类型PK ID。如果您同时拥有所有信息,则可以创建转码并首先插入车辆记录,然后插入子类型记录。然后提交你的transscation,否则回滚它。如果您想知道哪条记录属于哪种子类型表记录,您可以在车辆表中添加一列,例如可以有3个不同的值,例如0,1,2,表示哪条记录属于哪个子表。 java中的枚举可用于类似的内容以获得更多说明
答案 1 :(得分:0)
查看您提出的架构,我认为没有理由让您为每种车型分别设置表格,或者甚至是包含允许车辆类型的单独表格。您的车辆特定表基本上都是相同的,这意味着您可以轻松地折叠到单个表中,并且您可以使用ENUM字段来强制允许的车辆类型。
为什么不只是拥有如下车辆表?
CREATE TABLE IF NOT EXISTS `mydb`.`vehicles` (
`idvehicles` INT NOT NULL AUTO_INCREMENT,
`type` ENUM('airplane', 'automobile', 'bicycle') NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`idvehicles`),
INDEX `fk_vehicles_vehicle_types_idx` (`type` ASC))
ENGINE = InnoDB;
这种方法完全消除了5个表中的4个,这意味着在对这些记录执行CRUD操作时,您不再需要考虑使用连接,外键约束等。
答案 2 :(得分:0)
要强制执行独占子类型,请将type
指示符复制到每个子类型表中并使用复合外键约束:
CREATE TABLE IF NOT EXISTS `mydb`.`airplanes` (
`vehicles_idvehicles` INT NOT NULL,
`type` CHAR(8) NOT NULL,
`data_for_airplanes` VARCHAR(45) NULL,
PRIMARY KEY (`vehicles_idvehicles`),
CONSTRAINT `fk_airplanes_vehicles1`
FOREIGN KEY (`vehicles_idvehicles`, `type`)
REFERENCES `mydb`.`vehicles` (`idvehicles`, `type`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
接下来,您需要限制每个表中type
的值。不幸的是,MySQL不支持检查约束,因此您需要使用触发器:
DELIMITER ;;
CREATE TRIGGER airplanes_insert_type_check
BEFORE INSERT ON airplanes
FOR EACH ROW
BEGIN
IF NEW.`type` != 'airplane' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid type in airplanes';
END IF;
END;;
CREATE TRIGGER airplanes_update_type_check
BEFORE UPDATE ON airplanes
FOR EACH ROW
BEGIN
IF NEW.`type` != 'airplane' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Invalid type in airplanes';
END IF;
END;;
DELIMITER ;
因此,超类型表中的type
指标只匹配一个子类型表'由于触发器限制导致的type
指标,并将通过外键约束强制执行,防止重叠的子类型。