简体   繁体   English

Postgresql 唯一约束无效

[英]Postgresql Unique constraint not valid

I need to enforce a unique constraint on the table in a text field to make sure users dont input rows containing the same address.我需要对文本字段中的表强制执行唯一约束,以确保用户不会输入包含相同地址的行。 I do not want to validate it though, old records need to be kept我不想验证它,但需要保留旧记录

I have made some check constraints with a not valid clause but not sure how to make it unique我用无效子句做了一些检查约束,但不知道如何使它唯一

How to make a unique check constraint not valid如何使唯一检查约束无效

I would add a new column to the table:我会在表中添加一个新列:

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

Then old rows will be marked, and you can然后旧行将被标记,您可以

CREATE UNIQUE ON atable (col1) WHERE is_new;

which will act as a “conditional unique constraint”.这将充当“条件唯一约束”。

Note that adding a column with a default value will cause a (potentially slow) table rewrite before version 11.请注意,在版本 11 之前添加具有默认值的列将导致(可能很慢)表重写。

You can't:你不能:

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

"ADD table_constraint [ NOT VALID ] “添加 table_constraint [无效]

This form adds a new constraint to a table using the same constraint syntax as CREATE TABLE, plus the option NOT VALID, which is currently only allowed for foreign key and CHECK constraints."这种形式使用与 CREATE TABLE 相同的约束语法以及选项 NOT VALID 向表添加新约束,该选项当前仅允许用于外键和 CHECK 约束。”

Also CHECK constraints can only work on the current row so they can't enforce uniqueness across all rows. CHECK 约束也只能在当前行上起作用,因此它们不能在所有行中强制唯一性。 To do what you want you are looking at a ON INSERT trigger.要执行您想要的操作,您正在查看 ON INSERT 触发器。

If I understand correctly, you can do this by using a flag.如果我理解正确,您可以使用标志来执行此操作。 But you want to set the flag so exactly one row for each existing address has the flag set.但是您想设置标志,以便每个现有地址的一行都设置了标志。

ALTER TABLE t ADD address_for_duplicates boolean DEFAULT true NOT NULL;

Then, for existing rows, I will assume that you have a primary key, pk :然后,对于现有行,我将假设您有一个主键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;

Now add a filtered unique index:现在添加一个过滤的唯一索引:

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

This will prevent existing addresses from being duplicated (again) as well as new addresses.这将防止现有地址被复制(再次)以及新地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM