如何定义复合主键,甚至不允许反向组合

时间:2016-05-31 06:55:20

标签: mysql database-design constraints primary-key ddl

我正在构建一个App的好友列表,我想知道是否可以在一个表上定义键/索引,使得它不允许反向组合键。

例如,假设该表包含以下列:

user_id1, user_id2, status, [..timestamps]

主键是由user_id1user_id2组成的复合键。到目前为止没什么特别的。您可能会存储与此类似的数据:

+----------+-----------+----------+---------------------+---------------------+
| user_id1 |  user_id2 | status   | created_at          | updated_at          |
+----------+-----------+----------+---------------------+---------------------+
|        3 |         1 |    1     | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|        2 |         3 |    1     | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----------+-----------+----------+---------------------+---------------------+

但是这样就没有任何约束可以拒绝你分别为1, 33, 2插入user_id1user_id2 - 就像这样:

+----------+-----------+----------+---------------------+---------------------+
| user_id1 |  user_id2 | status   | created_at          | updated_at          |
+----------+-----------+----------+---------------------+---------------------+
|        3 |         1 |    1     | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|        2 |         3 |    1     | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|        1 |         3 |    1     | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|        3 |         2 |    1     | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----------+-----------+----------+---------------------+---------------------+

在这种情况下,谁是user1或user2并不重要,重要的是链接与否。重复不一定会破坏代码,但在MySQL中执行规则也会很好。

1 个答案:

答案 0 :(得分:2)

由于您并不真正关心哪个用户是user_id1,哪个用户是user_id2,我只是做出user_id1较低ID的任意决定(并确保应用程序在插入时对应用程序进行排序!)。

这样,您可以使用两个约束强制实现唯一性 - 首先,像您建议的复合主键:

ALTER TABLE friendship
ADD CONSTRAINT friendship_pk
PRIMARY KEY (user_id1, user_id2)

其次,您需要检查约束以确保user_id1确实是较小的ID,如上所述:

ALTER TABLE friendship
ADD CONSTRAINT friendship_ids_check
CHECK (user_id1 < user_id2)