我有以下数据库架构。
由于非NULL FK约束,确保每个父记录存在实体记录是微不足道的。
如何确保每条父记录都存在子记录?
-- MySQL Script generated by MySQL Workbench
-- 01/07/15 06:01:50
-- 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`.`entity`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`entity` (
`identity` INT NOT NULL,
`stuff` VARCHAR(45) NULL,
PRIMARY KEY (`identity`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`parent1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`parent1` (
`entity_identity` INT NOT NULL,
`stuff` VARCHAR(45) NULL,
PRIMARY KEY (`entity_identity`),
CONSTRAINT `fk_parent1_entity`
FOREIGN KEY (`entity_identity`)
REFERENCES `mydb`.`entity` (`identity`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`parent2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`parent2` (
`entity_identity` INT NOT NULL,
`stuff` VARCHAR(45) NULL,
PRIMARY KEY (`entity_identity`),
CONSTRAINT `fk_parent2_entity1`
FOREIGN KEY (`entity_identity`)
REFERENCES `mydb`.`entity` (`identity`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`child1_1`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`child1_1` (
`parent1_entity_identity` INT NOT NULL,
`stuff` VARCHAR(45) NULL,
PRIMARY KEY (`parent1_entity_identity`),
CONSTRAINT `fk_child1_1_parent11`
FOREIGN KEY (`parent1_entity_identity`)
REFERENCES `mydb`.`parent1` (`entity_identity`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`child1_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`child1_2` (
`parent1_entity_identity` INT NOT NULL,
`stuff` VARCHAR(45) NULL,
PRIMARY KEY (`parent1_entity_identity`),
CONSTRAINT `fk_child1_2_parent11`
FOREIGN KEY (`parent1_entity_identity`)
REFERENCES `mydb`.`parent1` (`entity_identity`)
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 :(得分:2)
我认为这必须由应用程序强制执行。
尝试使用触发器强制执行此操作会产生序列问题。如果您无法创建没有实体的父级,并且您无法创建没有父级的实体,那么您首先创建哪个实体?在您创建任一记录时,数据库引擎无法知道"知道"是否要在接下来的几毫秒内创建另一条记录。
但是,在代码中,您可以收集所有数据,然后在所有必需数据都可用的情况下写入两条记录,或者如果不存在则输出错误消息。
根据您的要求,您可能会在创建实体记录时触发一个触发器,该记录会自动使用默认值创建父记录,反之亦然。无论这样的虚拟记录是否有用,我都不能在不了解您的应用程序的情况下说出来。
你可以有一个创建Entity和Parent记录的存储过程,所以如果程序调用sproc,它必须创建两者。但是,在我熟悉的任何数据库引擎中,我都不知道程序可以创建记录的唯一方式是通过特定的存储过程。因此,强制使用该过程将依赖于遵循该约定的程序员。如果程序员遵循约定使用存储过程,他们应该能够遵循约定,始终通过他们使用的任何方法创建两个记录。
我的想法是创建一个创建该对的库函数,如果您没有创建两者所需的所有数据,则会返回某种错误条件。彻底调试此功能。然后告诉程序员总是使用这个函数来创建记录。然后,如果出现问题,可以查看一个地方。
答案 1 :(得分:0)
在您的设计中使用超类型将确保可以添加更多子表,而无需重新构建每个存在的表和应用程序。这意味着父母不会意识到孩子。
如果您面对的是没有孩子的父记录,可能是申请中存在缺陷的证据
BTW强制执行此检查约束的机制将使用触发器。
作为提示(如果使用ORM)将父实体作为抽象类将是另一种选择。