Group dependency SQL design

空扰寡人 提交于 2021-02-08 10:12:46

问题


I have an entity which has NOT NULL requirements based on the group it belongs to. For instance...

  • There are three types of churches: Buddhist, Muslim, and Christian.
  • All churches have some common required properties, however, each type of church has additional required properties.
  • All people have some common required properties, however, they have additional required properties based on the church type they belong to.
  • People must belong to one and only one church, however, may change their church to any other one of any religion provided that the above rules are met. The "type" of person they are is based on the church type they belong to.

How should entities who's required properties are based on the group which the entity belongs to be modeled? Or given my scenario, how should churches and people be modeled?

This is currently what I am doing, but it does not seem right. For instance, a person can be added before they become a Buddhist, Muslim, or Christian which breaks the rules. Also, a person or church can be more than one type which also breaks the rules.

-- MySQL Script generated by MySQL Workbench
-- 02/10/17 21:41:31
-- 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`.`churches`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches` (
  `idchurches` INT NOT NULL,
  `name` VARCHAR(45) NOT NULL,
  `address` VARCHAR(45) NOT NULL,
  `members` INT NOT NULL,
  PRIMARY KEY (`idchurches`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`churches_buddhist`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches_buddhist` (
  `churches_idchurches` INT NOT NULL,
  `number_of_buddas_in_church` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`churches_idchurches`),
  CONSTRAINT `fk_churches_buddhist_churches`
    FOREIGN KEY (`churches_idchurches`)
    REFERENCES `mydb`.`churches` (`idchurches`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`churches_muslim`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches_muslim` (
  `churches_idchurches` INT NOT NULL,
  `savior` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`churches_idchurches`),
  CONSTRAINT `fk_churches_muslim_churches1`
    FOREIGN KEY (`churches_idchurches`)
    REFERENCES `mydb`.`churches` (`idchurches`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`churches_christian`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`churches_christian` (
  `churches_idchurches` INT NOT NULL,
  `savior` VARCHAR(45) NOT NULL,
  `number_of_crosses_in_church` INT NOT NULL,
  PRIMARY KEY (`churches_idchurches`),
  CONSTRAINT `fk_churches_christian_churches1`
    FOREIGN KEY (`churches_idchurches`)
    REFERENCES `mydb`.`churches` (`idchurches`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`people`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`people` (
  `idpeople` INT NOT NULL,
  `name` VARCHAR(45) NOT NULL,
  `age` TINYINT NOT NULL,
  `race` VARCHAR(45) NOT NULL,
  `gender` VARCHAR(45) NOT NULL,
  `favoriteVegitable` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`idpeople`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`buddhists`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`buddhists` (
  `people_idpeople` INT NOT NULL,
  `WidthOfBelly` BIGINT NOT NULL,
  `LevelOfCconsciousness` INT NOT NULL,
  `churches_buddhist_churches_idchurches` INT NOT NULL,
  PRIMARY KEY (`people_idpeople`),
  INDEX `fk_buddhists_churches_buddhist1_idx` (`churches_buddhist_churches_idchurches` ASC),
  CONSTRAINT `fk_buddhists_people1`
    FOREIGN KEY (`people_idpeople`)
    REFERENCES `mydb`.`people` (`idpeople`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_buddhists_churches_buddhist1`
    FOREIGN KEY (`churches_buddhist_churches_idchurches`)
    REFERENCES `mydb`.`churches_buddhist` (`churches_idchurches`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`muslims`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`muslims` (
  `people_idpeople` INT NOT NULL,
  `DaysOffTakenForRamadan` INT NOT NULL,
  `favoriteMeat` VARCHAR(45) NOT NULL,
  `churches_muslim_churches_idchurches` INT NOT NULL,
  PRIMARY KEY (`people_idpeople`),
  INDEX `fk_muslims_churches_muslim1_idx` (`churches_muslim_churches_idchurches` ASC),
  CONSTRAINT `fk_muslims_people1`
    FOREIGN KEY (`people_idpeople`)
    REFERENCES `mydb`.`people` (`idpeople`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_muslims_churches_muslim1`
    FOREIGN KEY (`churches_muslim_churches_idchurches`)
    REFERENCES `mydb`.`churches_muslim` (`churches_idchurches`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`christians`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`christians` (
  `people_idpeople` INT NOT NULL,
  `ChristmasPresentsReceived` INT NOT NULL,
  `HolyMarysSaidPerDay` INT NOT NULL,
  `favoriteMeat` VARCHAR(45) NOT NULL,
  `FavoritePork` VARCHAR(45) NOT NULL,
  `churches_christian_churches_idchurches` INT NOT NULL,
  PRIMARY KEY (`people_idpeople`),
  INDEX `fk_christians_churches_christian1_idx` (`churches_christian_churches_idchurches` ASC),
  CONSTRAINT `fk_christians_people1`
    FOREIGN KEY (`people_idpeople`)
    REFERENCES `mydb`.`people` (`idpeople`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_christians_churches_christian1`
    FOREIGN KEY (`churches_christian_churches_idchurches`)
    REFERENCES `mydb`.`churches_christian` (`churches_idchurches`)
    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;

回答1:


One idiom declaratively enforcing disjoint subtypes:

  • add type discriminator/tag column religion_type to parent and child tables
  • add superkey UNIQUE NOT NULL (id, religion_type)to parent tables
  • add FOREIGN (super) KEY (id, religion_type) to child tables, referencing parents
  • add constraint CHECK( religion_type = 'religion' ) or constant computed column with value religion to child tables

This still doesn't enforce that every parent is a child. From this answer:

One needs triggers to reasonably constrain SQL databases. One uses idioms to get what declarative constraints one can.

Just find the straightforward predicate for each relevant application relationship and give it a table. Here, that's parent and child tables. The constraints follow from the predicates and possible situtations. Declare them to prevent impossible updates. Whenever values in some columns must appear in other columns we declare a FK. You don't have to think about a special case for subtyped entity ids. Certain ids will end up in certain tables because certain things are true of them. It is ultimately their satisfying different predicates that makes things of different "types", rather than vice versa.



来源:https://stackoverflow.com/questions/42165377/group-dependency-sql-design

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!