如何定义复合主键,它甚至不允许反向组合
问题描述:
我正在构建一个应用程序的朋友列表,我想知道是否有可能以某种方式定义表中的键/索引将不允许键的反向组合。如何定义复合主键,它甚至不允许反向组合
例如,让我们说,表中有这样的列:
user_id1, user_id2, status, [..timestamps]
主键是由user_id1
和user_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 |
+----------+-----------+----------+---------------------+---------------------+
但这样一来就没有约束可能会剥夺你分别插入用于user_id1
和user_id2
1, 3
或3, 2
- 像这样:
+----------+-----------+----------+---------------------+---------------------+
| 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中强制执行规则也不错。
答
既然你真的不关心哪个用户是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)
请使用明确的语言来表达您的要求。它几乎不能被制造出来。 – philipxy
我在这里挥舞着危险的红旗。你可以看到我吗?任何时候,如果在同一个表中有两列或更多列的值来自同一个信息域,那么您(可以说)违反了关系模型,并且(可以说更少)为您要讨厌的查询设置自己,或更晚。 –
@ Michael-sqlbot我有一种感觉。你能推荐一个替代结构吗? – zedling