这是我的多对多关系表:
Related:
-id
-id_postA
-id_postB
我要这个:
例如,如果有一行,id_postA = 32 and id_postB = 67
那么它必须忽略插入一行id_postA = 67 AND id_postB = 32
。
这是我的多对多关系表:
Related:
-id
-id_postA
-id_postB
我要这个:
例如,如果有一行,id_postA = 32 and id_postB = 67
那么它必须忽略插入一行id_postA = 67 AND id_postB = 32
。
一种选择是在两列上创建唯一索引:
CREATE UNIQUE INDEX uk_related ON related (id_postA, id_postB);
然后使用触发器、排序和on和on防止“按顺序反转重复”:id_postA
id_postB
INSERT
UPDATE
CREATE TRIGGER order_uk_related
BEFORE INSERT -- Duplicate this trigger also for UPDATE
ON related -- As MySQL doesn't support INSERT OR UPDATE triggers
FOR EACH ROW
BEGIN
DECLARE low INT;
DECLARE high INT;
SET low = LEAST(NEW.id_postA, NEW.id_postB);
SET high = GREATEST(NEW.id_postA, NEW.id_postB);
SET NEW.id_postA = low;
SET NEW.id_postB = high;
END;
正如您在此SQLFiddle中看到的那样,第四次插入将失败,因为触发器(2, 1)
已经切换到(1, 2)
:
INSERT INTO relation VALUES (1, null, null)
INSERT INTO relation VALUES (2, null, null)
INSERT INTO relation VALUES (3, 2, 1)
INSERT INTO relation VALUES (4, 1, 2)
在其他一些数据库中,您可能能够使用基于函数的索引。不幸的是,这在 MySQL 中是不可能的(在 MySQL 中是否可以有基于函数的索引?)。如果这是一个 Oracle 问题,你会写:
CREATE UNIQUE INDEX uk_related ON related (
LEAST(id_postA, id_postB),
GREATEST(id_postA, id_postB)
);
如果你总是用 A < B 插入这些,你就不必担心插入反向。这可以通过简单的排序或插入前的快速比较来完成。
像这样的连接表本质上是单向的。没有自动检测反向连接并使用简单UNIQUE
索引阻止它的方法。
但是,通常你会做的是成对插入:
INSERT INTO related (id_postA, id_postB) VALUES (3,4),(4,3);
如果此插入失败,则这些链接中的一个或两个已经存在。
你可以包括一个where
喜欢:
例如
insert into table_name
(id_postA
,id_postB
select
col1,
col2
from table_1
where where (cast(col1 as varchar)+'~'+cast(col2 as varchar))
not in (select cast(id_postB as varchar)+'~'+cast(id_postA as varchar) from table_name)