修复重复行以遵守约束

时间:2018-09-21 20:34:12

标签: postgresql

在添加唯一约束之前,是否有办法强制现有行在列上唯一?我将此约束添加到我的数据库中:

create unique index customfields_name_org_id_key 
on CustomFields(name, org_id) where deleted is false;

但是首先要查找所有不满足此约束的情况,然后在其中一个行的名称中加1(如果冲突行多于2,则增加数字)。因此,例如

SELECT name, org_id, deleted,
  row_number() OVER (PARTITION BY name, deleted ORDER BY org_id) AS rnum
FROM customfields ORDER BY org_id;

给我

   name    | org_id | deleted | rnum 
-----------+--------+---------+------
 Another   |      1 | f       |    1
 Bad email |      1 | t       |    1
 Dog?      |      1 | f       |    1
 New       |      1 | f       |    1
 New       |      1 | f       |    2
 New       |      1 | t       |    1
 New field |      1 | t       |    1

我想

 New       |      1 | f       |    2

要重命名为“ New2”

我已编写此代码:

update CustomFields
  set name  = case
         when cf.rnum = 1 or cf.deleted
         then cf.name
         else cf.name || rnum
      end
  from (SELECT name, org_id, deleted,
        row_number() OVER (PARTITION BY name, deleted ORDER BY org_id) AS rnum
FROM customfields ORDER BY org_id) as cf;

但是它只是从选择中取出第一行,并将所有名称重命名为“另一个”。如何更改此代码,以便更新在cf中的相应行上起作用?

示例代码:https://www.db-fiddle.com/#&togetherjs=iKSKze0tGm

1 个答案:

答案 0 :(得分:0)

您可以使用以下方法更新表格:

WITH cte AS (
   SELECT *,row_number() OVER (PARTITION BY name, deleted ORDER BY org_id) AS rnum
   FROM customfields
)
UPDATE CustomFields 
SET name  = (SELECT case when cf.rnum = 1 or cf.deleted then cf.name
                    else cf.name || rnum end
             FROM cte cf WHERE cf.id = CustomFields.id);

db<>fiddle demo