I would like to add a unique constraint to a DB field in one of my production databases. Unfortunately, the following statement is blocking:
ALTER TABLE package ADD CONSTRAINT unique_package_id UNIQUE (package_id);
Reading the relevant part from the PostgreSQL manual:
Note: Adding a constraint using an existing index can be helpful in situations where a new constraint needs to be added without blocking table updates for a long time. To do that, create the index using CREATE INDEX CONCURRENTLY, and then install it as an official constraint using this syntax. See the example below.
I tried:
CREATE UNIQUE INDEX CONCURRENTLY package_tmp_id_idx ON answer (package_id);
Followed by:
prod_db=> ALTER TABLE package ADD CONSTRAINT
unique_package_id UNIQUE (package) USING INDEX package_tmp_id_idx;
Which failed with:
ERROR: syntax error at or near "package_tmp_id_idx"
LINE 1: ...T unique_package_id UNIQUE (answer_id) USING INDEX package_tmp_id_idx...
^
I've tried playing with the syntax, but could not get it to work.
What's the right syntax to create a UNIQUE constraint using an existing UNIQUE index?
-
I tend not to add a unique constraint at all. This way, it is somewhat easier to solve issues with bloated indexes on heavily used tables.András Váczi– András Váczi2014年11月01日 12:37:02 +00:00Commented Nov 1, 2014 at 12:37
1 Answer 1
You don't specify the column for the unique constraint. That's not necessary because the column list is defined through the index:
ALTER TABLE package ADD CONSTRAINT
unique_package_id UNIQUE USING INDEX package_tmp_id_idx;
There is an example for that in the manual:
http://www.postgresql.org/docs/current/static/sql-altertable.html
You need to scroll down to the end of the page
-
Thanks. This query works syntactically, but it does not return for a long time (more than 5 minutes on a table with 3,000 rows). Could it be waiting for other transactions to finish?Adam Matan– Adam Matan2014年11月01日 06:46:22 +00:00Commented Nov 1, 2014 at 6:46
-
1@AdamMatan: yes the
ALTER TABLE
needs an exclusive lock (although for only a short time). If you have uncommitted transactions, then those will block this. Check for sessions that have the state "idle in transaction" inpg_stat_activity
user1822– user18222014年11月01日 07:48:47 +00:00Commented Nov 1, 2014 at 7:48 -
3What is the purpose of adding the
CONSTRAINT
if theUNIQUE INDEX
already exists? I tried testing around a bit and it seems that creating theUNIQUE INDEX
was sufficient to ensure uniqueness - trying to add duplicate data resulted induplicate key value violates unique constraint 'package_tmp_id_idx'
. I assume I'm missing something though, otherwise it wouldn't be in the manual, so any information is appreciated!dwanderson– dwanderson2018年03月19日 21:18:07 +00:00Commented Mar 19, 2018 at 21:18 -
What if my index has an expression? Then I need to specify the columns for the constraint right?Aakash Verma– Aakash Verma2022年01月28日 14:14:30 +00:00Commented Jan 28, 2022 at 14:14
-
2@dwanderson there are quite a few things that can only be done with constraints but not with index names; like upsert without listing every column in the unique indexSampson Crowley– Sampson Crowley2022年04月11日 02:39:29 +00:00Commented Apr 11, 2022 at 2:39
Explore related questions
See similar questions with these tags.