考虑下表:
+---------------------------------------------------------+
| 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中,从而有效避免原始问题。
但是有更好,更清洁的方法来达到同样的效果吗?
答案 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
。它会阻止重复插入。