【问题标题】:Altering Postgres table to have unique with constraint when duplicates records alredy exist当重复记录已经存在时,将 Postgres 表更改为具有唯一性约束
【发布时间】:2022-01-17 23:04:34
【问题描述】:

我们正在使用 Postgres 支持的 Django ORM。

我们有一些包含重复记录的表(“foo”),我们想要更改并添加一些唯一约束,这样就不会插入重复。

为此,我们首先需要删除重复的记录,然后添加唯一约束(否则使用alter table的添加约束会因为记录重复而失败)。

我想运行以下事务以实现上述流程 -

BEGIN WORK;

DELETE FROM foo
WHERE id IN
    (SELECT id
    FROM 
        (SELECT id,
        ROW_NUMBER() OVER( PARTITION BY a1, a2
        ORDER BY  id ) AS row_num
        FROM foo ) t
        WHERE t.row_num > 1 );

LOCK TABLE foo IN SHARE ROW EXCLUSIVE MODE;

DELETE FROM foo
WHERE id IN
    (SELECT id
    FROM 
        (SELECT id,
        ROW_NUMBER() OVER( PARTITION BY a1, a2
        ORDER BY  id ) AS row_num
        FROM foo ) t
        WHERE t.row_num > 1 );

ALTER TABLE "foo" ADD CONSTRAINT "some_constaint_name" UNIQUE ("a1", "a2");

COMMIT WORK;
  • 删除部分在这里两次,以最大限度地减少获取锁的时间
  • 锁是为了阻止 delete 和 alter 语句之间的更多重复插入)。

但是,这失败了 “无法 ALTER TABLE “foo”,因为它有待处理的触发事件”,我猜这是有道理的。

如果是这样,我该怎么做才能实现我想要的独特性? 由于表中的数据量很大,无法将数据复制到新表中...

【问题讨论】:

    标签: sql postgresql django-orm


    【解决方案1】:

    我看不到锁或两个删除语句的用途,但要立即执行触发器,请在 ALTER TABLE 之前运行它:

    SET CONSTRAINTS ALL IMMEDIATE;
    

    【讨论】:

    • 锁是为了阻止delete和alter语句之间更多的重复插入)。删除是为了删除重复,否则添加约束会失败。
    • 我认为更好的方法是运行 one DELETE,然后尝试创建一个唯一约束。如果由于竞争条件而失败,请重复整个过程。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    • 2015-03-01
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多