我有三张桌子。
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;
我是否需要在表userid
和photo
之间添加引用user
的外键,因为userid
和{{1}中已引用photo_article
复合外键?为什么呢?
答案 0 :(得分:0)
是
您的photo_article
外键仅强制photo
和article
之间的完整性。它不会强制user
的完整性。
user
和article
之间也没有外键。
这意味着如果您有以下数据:
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
文章"中。如果您更改了表articleid
或article
的含义,则应将其理解为RDBMS管理的一部分(除其他外)任何直接或可传递引用它们的外键也可能需要更改。
总是在明确与简洁之间以及冗余对于当前和/或可能的变化是否为正和/或否定之间进行工程权衡。