首页 文章

如何使用多个连接表构建数据库

提问于
浏览
5

这是我第一次尝试将更复杂的对象存储到数据库中 . 我需要一些数据库设计方面的帮助 .

recipe Object 我想从数据库中存储和重新生成

{
    "id": 2345,
    "name": "cake",
    "description": "yummy cake",
    "categorys": [
        17,
        26
    ],
    "persons": 4,
    "author": 26,
    "language": "de",
    "unit": "en",
    "variantOf": 34,
    "specialTools": [
        34,
        44,
        10
    ],
    "img": "32598734.jpg",
    "estTime": 2777,
    "steps": {
        "1": {
            "title": "mix",
            "description": "mix all together",
            "img": "45854.jpg",
            "timer": null,
            "ingredients": [
                {
                    "name": "Butter",
                    "color": "#227799",
                    "amount": 150,
                    "unit": "g"
                },
                {
                    "name": "egg",
                    "color": "#aaff22",
                    "amount": 3,
                    "unit": "pc"
                },
                {
                    "name": "sugar",
                    "color": "#22ffff",
                    "amount": 50,
                    "unit": "g"
                }
            ]
        },
        "2": {
            "title": "bake",
            "description": "put it in the oven",
            "img": null,
            "timer": 2400,
            "ingredients": [
                {
                    "name": "butter",
                    "color": "#227799",
                    "amount": null,
                    "unit": null
                },
                {
                    "name": "sugar",
                    "color": "#22ffff",
                    "amount": null,
                    "unit": null
                },
                {
                    "name": "egg",
                    "color": "#aaff22",
                    "amount": null,
                    "unit": null
                }
            ]
        }
    }
}

最复杂的部分是 steps 对象 . 每个配方可以具有不同数量的步骤,每个组合分配不同的成分 .

这是 database design 我做了
database scheme

recipe_id, step_id 是外键 . 我希望所有东西都在不同的表中,因为食谱应该按成分,分类排序......

SQL code 用于生成最重要的表

-- -----------------------------------------------------

-- Table `dev_Recipe`.`recipe`

-- -----------------------------------------------------

CREATE  TABLE IF NOT EXISTS `dev_Recipe`.`recipe` (

  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,

  `name` VARCHAR(255) NULL ,

  `description` TEXT NULL ,

  `author_id` INT UNSIGNED NOT NULL ,

  PRIMARY KEY (`id`) ,

  INDEX `author_id_idx` (`author_id` ASC) ,

  CONSTRAINT `author_id`

    FOREIGN KEY (`author_id` )

    REFERENCES `dev_Recipe`.`users` (`id` )

    ON DELETE NO ACTION

    ON UPDATE NO ACTION)

ENGINE = InnoDB;



-- -----------------------------------------------------

-- Table `dev_Recipe`.`step`

-- -----------------------------------------------------

CREATE  TABLE IF NOT EXISTS `dev_Recipe`.`step` (

  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,

  `recipe_id` INT UNSIGNED NOT NULL ,

  `step_number` INT UNSIGNED NOT NULL ,

  `description` TEXT NULL ,

  `timer` INT UNSIGNED NULL ,

  `image` VARCHAR(100) NULL ,

  PRIMARY KEY (`id`) ,

  INDEX `recipe_id_idx` (`recipe_id` ASC) ,

  CONSTRAINT `step_recipe_id`

    FOREIGN KEY (`recipe_id` )

    REFERENCES `dev_Recipe`.`recipe` (`id` )

    ON DELETE NO ACTION

    ON UPDATE NO ACTION)

ENGINE = InnoDB;


-- -----------------------------------------------------

-- Table `dev_Recipe`.`ingredient`

-- -----------------------------------------------------

CREATE  TABLE IF NOT EXISTS `dev_Recipe`.`ingredient` (

  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,

  `name` VARCHAR(45) NOT NULL ,

  `color` INT NOT NULL ,

  `img` VARCHAR(45) NULL ,

  PRIMARY KEY (`id`) )

ENGINE = InnoDB;


-- -----------------------------------------------------

-- Table `dev_Recipe`.`step_ingredients`

-- -----------------------------------------------------

CREATE  TABLE IF NOT EXISTS `dev_Recipe`.`step_ingredients` (

  `recipe_id` INT UNSIGNED NOT NULL ,

  `ingredient_id` INT UNSIGNED NOT NULL ,

  `step_id` INT UNSIGNED NOT NULL ,

  `amount` INT NULL ,

  `unit` VARCHAR(25) NULL ,

  INDEX `recipe_id_idx` (`recipe_id` ASC) ,

  INDEX `ingredient_id_idx` (`ingredient_id` ASC) ,

  INDEX `step_id_idx` (`step_id` ASC) ,

  PRIMARY KEY (`recipe_id`, `step_id`) ,

  CONSTRAINT `step_ing_recipe_id`

    FOREIGN KEY (`recipe_id` )

    REFERENCES `dev_Recipe`.`recipe` (`id` )

    ON DELETE NO ACTION

    ON UPDATE NO ACTION,

  CONSTRAINT `ingredient_step_ing_id`

    FOREIGN KEY (`ingredient_id` )

    REFERENCES `dev_Recipe`.`ingredient` (`id` )

    ON DELETE NO ACTION

    ON UPDATE NO ACTION,

  CONSTRAINT `step_ing_id`

    FOREIGN KEY (`step_id` )

    REFERENCES `dev_Recipe`.`step` (`id` )

    ON DELETE NO ACTION

    ON UPDATE NO ACTION)

ENGINE = InnoDB;

由于我之前从未做过连接表,所以我不知道这是否是解决我问题的正确方法 . 它是一个合理的设计,如何优化它?

我做了另一个设计,其中 recipesstepstepingredients 连接 . 我认为第一个布局更容易查询,因为我只能通过查看 step_ingredients 来搜索 ingredients_id recipe_id ,但我不确定 . 有什么想法吗?

database design 2

2 回答

  • 5

    关系数据库设计的主要内容是有3种类型的FK关系:

    • 1比1

    • 1对多

    • 多对多

    话虽如此,您的架构看起来很正常,逻辑一目了然 . 我要提出的唯一警告是,对于具有自引用的类别,SQL中的递归可能很棘手 .

    几点说明:

    步骤成分需要一个已经有recipe_id的步骤(可能为null)

    可以在没有步骤的情况下存在步骤成分

    没有配方就可以存在一个步骤

    用户与食谱是一对一的(正如丹所提到的)

    编辑:关于双连接而不是单个连接从配方到配料的关注,这是一个标准化问题我很难用原始设计:什么使step_ingredient和步骤recipe_id保持不变?现在,不能保证一致性 . 如果你考虑数据设计你真的说你认为你会加入这两个表很多,那么为什么不用不必要的FK连接它们(不要这样做或者事情会变得很乱:))

    您的第二个设计实际上也允许相同数量的连接,因为您已将recipe_id作为PK包含在步骤表中,然后在step_ingredient中成为PK / FK,它将保证recipe_id的一致性 . 例如:

    SELECT ingredient_id
    FROM Recipe r
    JOIN Step_ingredient si on si.step_recipe_id = r.recipe_id
    JOIN Ingredient i on si.ingredient_id = i.ingredient_id
    

    和我最喜欢的数据库规范化入门链接:http://en.wikipedia.org/wiki/Database_normalization

  • 2

    乍一看它看起来非常好 . 但是,我不确定为什么类别和成分类别表需要父ID .

    此外,您需要用户和食谱之间的多对多关系 . 您目前看起来像是一对一的 .

相关问题