外键冗余

时间:2015-06-27 08:28:31

标签: mysql sql database foreign-keys rdbms

我有三张桌子。

用户

CREATE TABLE user(
    userid INT UNSIGNED AUTO_INCREMENT NOT NULL,
    name VARCHAR(100) NOT NULL,
    time DATETIME NOT NULL,
    PRIMARY KEY(userid),
) ENGINE=InnoDB;

制品

CREATE TABLE article(
    userid INT UNSIGNED NOT NULL,
    subid INT UNSIGNED NOT NULL,
    content VARCHAR(1000) NOT NULL,
    time DATETIME NOT NULL,
    PRIMARY KEY(userid,subid),
    FOREIGN KEY article_user(userid) REFERENCES user(userid) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;

照片

CREATE TABLE photo(
    userid INT UNSIGNED NOT NULL,
    subid INT UNSIGNED NOT NULL,
    articleid INT UNSIGNED NOT NULL,
    name VARCHAR(255) NOT NULL,
    time DATETIME NOT NULL,
    PRIMARY KEY(userid,subid),
    FOREIGN KEY photo_article(userid,articleid) REFERENCES article(userid,subid) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;

我是否需要在表useridphoto之间添加引用user的外键,因为userid和{{1}中已引用photo_article复合外键?为什么呢?

2 个答案:

答案 0 :(得分:0)

您的photo_article外键仅强制photoarticle之间的完整性。它不会强制user的完整性。

userarticle之间也没有外键。

这意味着如果您有以下数据:

用户

userid | name | time
-------|------|-----------------
1      | foo  | 1970-01-01 10:00
3      | bar  | 1970-01-01 12:00

制品

userid | subid | content | time
-------|-------|---------|-----------------
1      | 1     | lorem   | 1970-01-01 10:15
2      | 2     | ipsum   | 1970-01-01 11:15
3      | 3     | dolor   | 1970-01-01 12:15

照片

userid | subid | articleid | name | time
-------|-------|-----------|------|-----------------
1      | 1     | 1         | foo  | 1970-01-01 10:30
2      | 2     | 2         | bar  | 1970-01-01 11:30

此数据有效,即使用户中不存在userid 2(假设userid中有profiles 2)。

答案 1 :(得分:0)

不是必要FOREIGN KEY声明表示引用表中的子行也必须在引用的表中显示为唯一的子行。执行你声明的那些将强制执行你没有做过的那个。

但您可能会或可能不想申报。可能,不是。 photo中每一行的含义类似于"用户subid的{​​{1}}照片会显示在他们的serid文章"中。如果您更改了表articleidarticle的含义,则应将其理解为RDBMS管理的一部分(除其他外)任何直接或可传递引用它们的外键也可能需要更改。

总是在明确与简洁之间以及冗余对于当前和/或可能的变化是否为正和/或否定之间进行工程权衡。