3

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

1
  • Please provide sample data and desired results so it is really clear what you want to do. Commented Jun 26, 2020 at 12:47

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

. . This will not prevent duplicates between new rows and existing rows. I am guessing the OP wants to preclude those as well (I certainly would in this situation).
2

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:

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.

Comments

1

You can't:

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

"ADD table_constraint [ NOT VALID ]

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."

Also CHECK constraints can only work on the current row so they can't enforce uniqueness across all rows. To do what you want you are looking at a ON INSERT trigger.

1 Comment

... but keep in mind that with triggers as constraints, there is usually a race condition.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.