MySQL Composite PK 与 Nullable FK

标签 mysql database-design foreign-keys data-modeling nullable

首先,让我先声明一下我确实是一个非常糟糕的数据建模师。我所知道的只够危险的。

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

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_userfk_reputation_log_user1。每个声誉事件都有一个给予者,但只有一些事件有一个接收者。我希望这个 FK 可以为空,但我不知道如何做到这一点,或者它是否被“允许”。

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

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

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

最佳答案

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 要求,您是否知道可以对可为空的列声明 UNIQUE 约束。列可能包含NULL(与主键约束不同)。这是标准的 SQL 行为,并且受 MySQL 支持。

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

关于MySQL Composite PK 与 Nullable FK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/334830/

相关文章:

MySQL:自定义行验证

sql - MySQL:如何以编程方式确定外键关系?

php - SQL 选择具有字符限制的所有列

php - Laravel 5.1 从原始数据库(或只是一个数组)创建集合或关联数组

database-design - 为 SO 类型的站点创建 "categories"是否值得,或者标签是否可以替代?

sql - 如何在记录更改时更新不同位置(表)的多个信息?

MongoDB 的可扩展性设计

mysql - 在 Ruby 中的嵌入式 SQL 查询中使用数组

PHP MySQL WHERE SUM WHERE SUBSTRING

不同数据库之间的 MySQL InnoDB 外键