【问题标题】:Postgresql Unique constraint not validPostgresql唯一约束无效
【发布时间】:2020-06-26 12:45:23
【问题描述】:

我需要对文本字段中的表实施唯一约束,以确保用户不会输入包含相同地址的行。不过我不想验证它,需要保留旧记录

我用无效子句做了一些检查约束,但不知道如何使它唯一

如何使唯一检查约束无效

【问题讨论】:

  • 请提供样本数据和期望的结果,以便清楚您想要做什么。

标签: sql postgresql


【解决方案1】:

我会在表格中添加一个新列:

ALTER TABLE atable ADD is_new boolean DEFAULT FALSE NOT NULL;
ALTER TABLE atable ALTER is_new SET DEFAULT TRUE;

那么旧的行就会被标记出来,你可以

CREATE UNIQUE ON atable (col1) WHERE is_new;

这将充当“条件唯一约束”。

请注意,添加具有默认值的列将导致 11 版之前的表重写(可能很慢)。

【讨论】:

  • 。 .这不会阻止 new 行和 existing 行之间的重复。我猜 OP 也想排除这些(在这种情况下我当然会)。
【解决方案2】:

你不能:

https://www.postgresql.org/docs/current/sql-altertable.html

"添加 table_constraint [无效]

此表单使用与 CREATE TABLE 相同的约束语法以及当前仅允许外键和 CHECK 约束的选项 NOT VALID 向表添加新约束。”

此外,CHECK 约束只能在当前行上起作用,因此它们不能在所有行中强制唯一性。要执行您想要的操作,您正在查看 ON INSERT 触发器。

【讨论】:

【解决方案3】:

如果我理解正确,您可以使用标志来执行此操作。但是您想设置标志,以便每个现有地址的一行都设置了标志。

ALTER TABLE t ADD address_for_duplicates boolean DEFAULT true NOT NULL;

然后,对于现有的行,我会假设你有一个主键,pk

update t
    set address_for_duplicates = (seqnum = 1)
    from (select t.*, row_number() over (partition by address order by pk) as seqnum
          from t
         ) tt
    where tt.pk = t.pk;

现在添加一个过滤的唯一索引:

create unique index unq_t_address_some_duplicates
    on t(address)
    where address_for_duplicates;

这将防止现有地址被复制(再次)以及新地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多