如何避免这种重复?

时间:2013-05-10 16:54:13

标签: mysql

这是我与许多关系的表格:

Related:
-id
-id_postA
-id_postB

我想要这个:

例如,如果有一行 id_postA = 32 and id_postB = 67 然后它必须忽略使用 id_postA = 67 AND id_postB = 32 插入行。

3 个答案:

答案 0 :(得分:1)

一种选择是在两列上创建unique index

CREATE UNIQUE INDEX uk_related ON related (id_postA, id_postB);

然后使用trigger阻止“按顺序反转重复”,在id_postAid_postB上排序INSERTUPDATE }:

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中是不可能的(Is it possible to have function-based index in MySQL?)。如果这是一个Oracle问题,你可以写:

CREATE UNIQUE INDEX uk_related ON related (
    LEAST(id_postA, id_postB), 
    GREATEST(id_postA, id_postB)
);

答案 1 :(得分:0)

您可以添加 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)

答案 2 :(得分:0)

如果你总是用A< B,您不必担心插入反向。这可以通过简单的排序或插入前的快速比较来完成。

像这样加入表格本质上是单向的。没有自动方法来检测反向连接并使用简单的UNIQUE索引阻止它。

通常,你要做的是成对插入:

INSERT INTO related (id_postA, id_postB) VALUES (3,4),(4,3);

如果此插入失败,则其中一个或两个链接已存在。

相关问题