如何建模这种关系(避免循环)?

时间:2014-10-31 14:43:07

标签: mysql

在MySQL中...这可能不是我追求的关系中最好的例子,但它本质上是我在我的数据库中尝试做的事情(这完全是从我的完整数据模型中简化的)。 / p>

假设我们有一个名为author的表和一个名为book的表。

  • 'DB.author':author_id,author_name
  • 'DB.book':book_id,book_name,author_id (这是一种识别关系)

现在假设我们有一个名为reader的表格,其中列有喜欢的作者和最喜欢的书籍。每个读者都有一个最喜欢的作家,但他们并不都有一本喜欢的书。如果他们确实有一本喜欢的书,那一定是他们最喜欢的作家写的。

  • 'DB.reader':reader_id,reader_name,favorite_author_id,favorite_book_id

我不能只删除favorite_author_id列,因为favorite_book_id可能为null。是否有可能对这种关系建模并避免循环?

3 个答案:

答案 0 :(得分:0)

或许有一个reader_favorite表格,其中包含reader_idfavorite_typefavorite value,其中favorite_type可能是一本书或作者。然后,您可以从reader LEFT JOIN到reader_favorite,然后从book表左键加入authorreader_favorite

然后你只能确保如果读者在book表中有authorreader_favorite个喜欢的类型的条目,那么这两个值是一致的,但是这已经是一个问题所以:没有伤害,没有犯规。

答案 1 :(得分:0)

你可以尝试使用单独的表:favorites:object_id,object_type,(或类似的东西),然后你会在reader表中找到喜欢的id的单列。这也可以更具扩展性,但它仍然不是很好。

另一个选项(一般来说)可能是约束(并保留你描述的结构),但我认为这对MySQL有问题

答案 2 :(得分:0)

回答我自己的问题。事实证明,我能够使用MySQL / InnoDB中的外键约束来完成这项工作。我认为我不能拥有有时包含空值的复合外键,但它可以按预期工作。

CREATE TABLE `author` (
  `author_id` int(11) NOT NULL AUTO_INCREMENT,
  `author_name` varchar(20) NOT NULL,
  PRIMARY KEY (`author_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

CREATE TABLE `book` (
  `book_id` int(11) NOT NULL AUTO_INCREMENT,
  `book_name` varchar(25) NOT NULL,
  `author_id` int(11) NOT NULL,
  PRIMARY KEY (`book_id`,`author_id`),
  KEY `fk_book_author` (`author_id`),
  CONSTRAINT `fk_book_author` FOREIGN KEY (`author_id`) REFERENCES `author` (`author_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;

CREATE TABLE `reader` (
  `reader_id` int(11) NOT NULL AUTO_INCREMENT,
  `reader_name` varchar(20) NOT NULL,
  `favorite_author_id` int(11) NOT NULL,
  `favorite_book_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`reader_id`),
  KEY `fk_reader_favorite_book` (`favorite_book_id`,`favorite_author_id`),
  KEY `fk_reader_favorite_author` (`favorite_author_id`),
  CONSTRAINT `fk_reader_favorite_author` FOREIGN KEY (`favorite_author_id`) REFERENCES `author` (`author_id`),
  CONSTRAINT `fk_reader_favorite_book` FOREIGN KEY (`favorite_book_id`, `favorite_author_id`) REFERENCES `book` (`book_id`, `author_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;