代码之家  ›  专栏  ›  技术社区  ›  Peter Bailey

具有可为空FK的MySQL复合PK

  •  2
  • Peter Bailey  · 技术社区  · 17 年前

    首先,让我在回答这个问题之前说,我真的是一个非常糟糕的数据建模师。我只知道足够危险。

    我正在构建的表有四个外键,其中两个引用同一个表。这是该表的create语句。

    CREATE  TABLE IF NOT EXISTS `abnr`.`reputation_event_log` (
      `id` INT NOT NULL AUTO_INCREMENT ,
      `reputation_event_id` INT NULL ,
      `giver_user_id` INT NULL ,
      `receiver_user_id` INT NULL ,
      `review_id` INT NULL ,
      `giver_point_value` SMALLINT NULL DEFAULT 0 ,
      `receiver_point_value` SMALLINT NULL DEFAULT 0 ,
      `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
      PRIMARY KEY (`id`) ,
      INDEX `fk_reputation_log_user` (`giver_user_id` ASC) ,
      INDEX `fk_reputation_log_user1` (`receiver_user_id` ASC) ,
      INDEX `fk_reputation_log_review` (`review_id` ASC) ,
      INDEX `fk_reputation_log_reputation_event` (`reputation_event_id` ASC) ,
      CONSTRAINT `fk_reputation_log_user`
        FOREIGN KEY (`giver_user_id` )
        REFERENCES `abnr`.`user` (`id` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_reputation_log_user1`
        FOREIGN KEY (`receiver_user_id` )
        REFERENCES `abnr`.`user` (`id` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_reputation_log_review`
        FOREIGN KEY (`review_id` )
        REFERENCES `abnr`.`review` (`id` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION,
      CONSTRAINT `fk_reputation_log_reputation_event`
        FOREIGN KEY (`reputation_event_id` )
        REFERENCES `abnr`.`reputation_event` (`id` )
        ON DELETE NO ACTION
        ON UPDATE NO ACTION)
    ENGINE = InnoDB
    DEFAULT CHARACTER SET = utf8
    COLLATE = utf8_general_ci;
    

    我关注的这篇文章的索引是 fk_reputation_log_user fk_reputation_log_user1 每个声誉事件都有给予者,但只有一些有接受者。我愿意 喜欢 这个FK可以为空,但我不知道如何做到这一点,或者它是否被“允许”。

    我还考虑过将所有FK列都作为主键的一部分,以对重复的日志条目进行数据库级保护的想法,但这行不通,因为PK列必须不为NULL。

    如果您需要更多详细信息,请在评论中说明。谢谢!

    (是的,这是一个与SO没有太大区别的声誉系统)

    1 回复  |  直到 17 年前
        1
  •  4
  •   Bill Karwin    17 年前
    CREATE  TABLE IF NOT EXISTS `abnr`.`reputation_event_log` (
      `id`                  INT NOT NULL AUTO_INCREMENT ,
      `reputation_event_id` INT NULL ,
      `giver_user_id`       INT NOT NULL , -- mandatory giver_user_id
      `receiver_user_id`    INT NULL ,     -- optional receiver_user_id
      . . .
    

    是的,你可以 NULL 在声明了外键约束的列中 NOT NULL 列上的约束独立于该列上的任何外键约束。

    外键意味着 如果 该列具有非NULL值,则该值必须存在于外键约束引用的表的主键中。

    编辑: 至于你的 UNIQUE 要求,您是否知道可以申报 独特的 对可空列的约束。柱子 五月 包含 无效的 s(与主键约束不同)。这是标准的SQL行为,MySQL支持。

      . . .
      PRIMARY KEY (`id`),
      CONSTRAINT UNIQUE (`giver_user_id`, `receiver_user_id`, 
                         `review_id`, `reputation_event_id`),
      . . .