【问题标题】:How to define Composite primary key, which doesn't allow even the reverse combination如何定义复合主键,甚至不允许反向组合
【发布时间】:2016-09-29 01:25:03
【问题描述】:

我正在为一个应用程序建立一个朋友列表,我想知道是否可以以不允许键的反向组合的方式定义表上的键/索引。

例如,假设表格有如下列:

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 |
+----------+-----------+----------+---------------------+---------------------+

但是这样就没有约束会拒绝您分别为user_id1user_id2 插入1, 33, 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 |
+----------+-----------+----------+---------------------+---------------------+

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

【问题讨论】:

  • 请用清晰的语言表达您的要求。几乎看不出来。
  • 我在这里挥舞危险的红旗。你可以看到我吗?每当您在同一个表中有两个或多个列的值来自同一个信息域时,您(可以说)违反了关系模型,并且(可以说)为自己设置了您将讨厌的查询,更快或更高版本。
  • @Michael-sqlbot 我有一种感觉。你能推荐一个替代结构吗?
  • 有些事情最好在应用程序中完成,而不是 SQL。

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


【解决方案1】:

由于您并不真正关心哪个用户是 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)

【讨论】:

  • 这是一种有趣且开箱即用的方法;会试试先生!
  • @zedling & Mureinik MySQL 仍然不强制 CHECK 约束(尽管它会解析它们)。
  • 似乎是这样,我甚至可以将相同的值保存到两个字段,并且不会引发错误。我唯一的想法是插入/更新之前的某种触发器
  • 不幸的是 MySQL 只是跳过了 CHECK 约束。 See thisThe CHECK clause is parsed but ignored by all storage engines.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 2014-06-27
  • 2010-11-09
  • 2013-08-22
  • 2021-08-31
  • 1970-01-01
相关资源
最近更新 更多