用户关系表 - 避免重复

时间:2013-11-03 13:50:26

标签: mysql

考虑下表:

+---------------------------------------------------------+
|               relationships                             |
+---------------------------------------------------------+
| id | user_id_1  |  user_id_2   |  status_1  |  status_2 |
+----+------------+--------------+------------------------+
|    |            |              |            |           |
|    |            |              |            |           |
|    |            |              |            |           |
|    |            |              |            |           |
+---------------------------------------------------------+

我想约束,user_id_1和user_id_2 我不想要重复:

user_id_1 = 1 and user_id_2 = 2
user_id_1 = 2 and user_id_2 = 1

这两个对我的申请基本相同。

我避免重复的策略是在插入之前订购user_id,并且总是将较小的一个放在user_id_1中,将较大的id放在user_id_2中,从而有效避免原始问题。

但是有更好,更清洁的方法来达到同样的效果吗?

3 个答案:

答案 0 :(得分:0)

如果您将用户存储在不同行的同一列中,则可以利用PRIMARY KEY来强制实现唯一性:

CREATE TABLE relationships (
  rel_id INT,
  user_id INT,
  status INT,
  PRIMARY KEY (rel_id, user_id)
);

将用户输入此表的顺序无关紧要。

INSERT INTO relationships (rel_id, user_id) VALUES (1234, 1), (1234, 2);

与以下内容相同:

INSERT INTO relationships (rel_id, user_id) VALUES (1234, 2), (1234, 1);

因为它们最终在不同的行上。他们最终会自动订购,因为这些列是主键的一部分。

答案 1 :(得分:0)

在Oracle中,您可以按如下方式实现:

SQL> create table t1 (a integer,b integer);

Table created.

SQL> create unique index ck_t1_ab on t1(least(a,b),greatest(a,b));

Index created.

SQL>
insert into t1 (a,b) values (1,2);

1 row created.

SQL> insert into t1 (a,b) values (2,1);
insert into t1 (a,b) values (2,1)
*
ERROR at line 1:
ORA-00001: unique constraint (SIMON.CK_T1_AB) violated

可悲的是,我在MySQL中很快对此进行了测试,似乎并不支持它。我不建议滥用你的表的PRIMARY KEY,而是实现像这样的CHECK约束:

alter table t1 add constraint uq_t1_ab unique(a,b);
alter table t1 add constraint uq_t1_ba unique(b,a);

然后,您的解决方法(在输入之前对值进行排序)应该可以正常工作。

答案 2 :(得分:0)

假设您有UNIQUE约束

ALTER TABLE relationships ADD UNIQUE(user_id_1, user_id_2);

一种可能的解决方案是在使用BEFORE触发器插入时透明地重新排序用户ID

DELIMITER $$
CREATE TRIGGER tg_bi_relationships
BEFORE INSERT ON relationships
FOR EACH ROW
BEGIN
  DECLARE _least, _greatest INT;
  SET _least    = LEAST(NEW.user_id_1, NEW.user_id_2),
      _greatest = GREATEST(NEW.user_id_2, NEW.user_id_1);
  SET NEW.user_id_1 = _least,
      NEW.user_id_2 = _greatest;
END$$
DELIMITER ;

这是 SQLFiddle 演示。 尝试取消注释架构窗格中的最后一个INSERT,然后点击Build Schema。它会阻止重复插入。