【问题标题】:How to ignore duplicates without unique constraint in Postgres 9.4?如何在 Postgres 9.4 中忽略没有唯一约束的重复项?
【发布时间】:2020-09-10 05:32:22
【问题描述】:

我目前在我们的旧数据库(postgres 9.4)表中遇到一个问题,该表包含一些重复的行。我想确保不再生成重复的行。

但我也想保留已经生成的重复行。因此,我无法对这些列(多列)应用唯一约束。

我创建了一个触发器,它会检查该行是否已存在并相应地引发异常。但是在处理并发事务时它也会失败。

例子:

TAB1

col1   |  col2  |  col3  |
------------------------------------
1      |  A     |  B     |   -- 
2      |  A     |  B     |   -- already present duplicates for column col2 and col3(allowed)
3      |  C     |  D     |

INSERT INTO TAB1 VALUES(4 , 'A' , 'B') ; -- This insert statement will not be allowed.

注意:由于数据库版本较旧,我无法在冲突中使用

【问题讨论】:

  • 您能提供更多信息,例如表结构和一些示例行吗?这将允许其他人模拟您的问题并为您提供更快更好的答案。
  • @WilliamPrigolLopes 我添加了一个示例。

标签: sql postgresql duplicates postgresql-9.4


【解决方案1】:

大概,您不希望新行重复历史行。如果是这样,您可以这样做,但需要修改表并添加新列。

alter table t add duplicate_seq int default 1;

然后更新此列以识别现有重复项:

update t
    set duplicate_seq = seqnum
    from (select t.*, row_number() over (partition by col order by col) as seqnum
          from t
         ) tt
    where t.<primary key> = tt.<primary key>;

现在,创建一个唯一索引或约束:

alter table t add constraint unq_t_col_seq on t(col, duplicate_seq);

当您插入行时,不要为duplicate_seq 提供值。默认为1。这将与任何现有值冲突 - 或与最近输入的重复值冲突。允许重复历史记录。

【讨论】:

  • 这是一个非常好的解决方案,我将实施它。但只是为了好奇,有没有其他不改变表的方法。
  • @SABER-FICTIONALCHARACTER 。 . .尽管我不是 100% 确定,但可以将您的触发器与 pilfor 建议的过滤的唯一约束结合使用。您也可以通过在插入上使用表锁来处理它,但大概您不想产生这么多开销
【解决方案2】:

您可以尝试创建一个partial index 以仅对表行的子集具有唯一约束:

例如:

create unique index on t(x) where (d > '2020-01-01');

【讨论】:

  • 虽然是一个合理的解决方案,但这允许新行复制历史值。
猜你喜欢
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 2015-03-06
  • 1970-01-01
相关资源
最近更新 更多