删除所有违反新的唯一约束的记录

问题描述 投票:0回答:2

我有一个包含以下字段的表

----------------------------------
|  id  |  user_id   |   doc_id   |
----------------------------------

我想创建一个新的唯一约束以确保不存在重复的 user_id 和 doc_id 记录。也就是说,一个用户只能链接到一个文档一次。这很简单。

ALTER TABLE mytable
    ADD CONSTRAINT uniquectm_const UNIQUE (user_id, doc_id);

问题是我的记录当前违反了该限制。我想知道是否有一种简单的方法来查询这些记录或告诉 postgres 删除任何违反约束的内容。

postgresql duplicates sql-delete
2个回答
3
投票

识别违反新密钥的记录:

SELECT *
FROM
   (
      SELECT id, user_id, doc_id
         , COUNT(*) OVER (PARTITION BY user_id, doc_id) as unique_check
      FROM mytable
   )
WHERE unique_check > 1;

然后您可以从这些重复项中找出哪些应该删除并执行删除。

据我所知,没有其他方法可以执行此操作,因为任何自动的“删除任何重复项”命令都会让数据库引擎决定删除两个或多个重复记录中的哪一个。

如果整个记录是重复的(所有列都匹配),那么您可以使用新的唯一约束创建一个新表并执行

INSERT INTO newtable SELECT DISTINCT * FROM oldtable
但我打赌情况并非如此。


0
投票

我会像这样修改@JNevill 的查询:

SELECT *
FROM
   (
      SELECT id, user_id, doc_id,
        ROW_NUMBER() OVER (PARTITION BY user_id, doc_id ORDER BY id ASC) AS num
      FROM mytable
   )
WHERE num > 1;

真正重要的两个区别是:

  1. 我正在使用
    ROW_NUMBER()
    而不是
    COUNT()
  2. ORDER BY
    接下来是
    PARTITION BY

使用

COUNT(*)
,您可以获得每个
user_id
doc_id
对的冲突行总数。但是使用
ROW_NUMBER()
你可以将它们排序为 1、2、3 等,因此最终的
dup_num > 1
将为你提供需要删除以满足约束的最少行,而不是所有有问题的行。此外,通过更改
ORDER BY
标准,您可以决定是否获取最新、最旧或哪种类型的行(在上面的示例中,是违反约束的最新行)。

© www.soinside.com 2019 - 2024. All rights reserved.