在违反行的多个列上添加唯一约束

时间:2012-04-03 18:08:44

标签: postgresql unique-constraint alter

我们试图以删除重复项而不是抛出错误的方式为postgres表添加唯一约束。唯一约束跨越两列,并且没有主键。例如:

i_id | term   | date_created
1    | 'mako' | 123456789
1    | 'mako' | 123451234
1    | 'tele' | 213456852
2    | 'rake' | 598521542

因此,在这个例子中,我们需要删除第二行才能安全地添加唯一约束。通常我们会执行一个带有select distinct的delete命令,但是我们没有任何行的区别键。具体来说,唯一键将位于列[i_id,term]。

之上

(WTF从一开始就没有一个独特的约束?去图。)

我认为删除声明是最好的,但我不能简单地写

delete from table where row_id not in (select row_id ... distinct something ... )

因为该行没有主键。如果可能的话,我宁愿避开临时桌子。有什么建议吗?

编辑:抱歉。我们正在使用postgres 8.4。

编辑2:我们使用的解决方案是:

delete from table where ctid not in (
  select 
    distinct on (i_id, term)
    ctid
    from table
    order by i_id, term
);

谢谢你们!

2 个答案:

答案 0 :(得分:2)

DELETE FROM the_table
WHERE ctid NOT IN (SELECT min(b.ctid)
                   FROM the_table b
                   GROUP BY b.i_id, b.term)

答案 1 :(得分:0)

看起来你的dup在date_created列中有区别,所以你可以使用windowing函数捕获除了重复集的第一行以外的所有值,然后用它来删除额外的行

delete from foo
using 
(select i_id, term, date_created
 from (
  select foo.*
    , row_number() over (partition by i_id, term order by date_created asc) the_rank
  from foo
 ) ranked
 where ranked.the_rank <> 1
) extras
where foo.i_id = extras.i_id and foo.term = extras.term and foo.date_created = extras.date_created;

这与欧文的回答大致相似。它在选择要保留的最旧条目而不是最新条目方面有所不同,可以通过在排序子查询中将ASC从ASC更改为DESC来更改。

相关问题