Unnamed Constraints
Check name: UnnamedConstraintCheck
Lock type: None (best practice warning)
Bad
Adding constraints without explicit names results in auto-generated names from Postgres. These names vary between databases and make future migrations difficult — you can’t reliably reference a constraint you don’t know the name of.
-- Unnamed UNIQUE constraint
ALTER TABLE users ADD UNIQUE (email);
-- Unnamed FOREIGN KEY constraint
ALTER TABLE posts ADD FOREIGN KEY (user_id) REFERENCES users(id);
-- Unnamed CHECK constraint
ALTER TABLE users ADD CHECK (age >= 0);
Good
Always name constraints explicitly using the CONSTRAINT keyword:
-- Named UNIQUE constraint
ALTER TABLE users ADD CONSTRAINT users_email_key UNIQUE (email);
-- Named FOREIGN KEY constraint
ALTER TABLE posts ADD CONSTRAINT posts_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
-- Named CHECK constraint
ALTER TABLE users ADD CONSTRAINT users_age_check CHECK (age >= 0);
Naming Conventions
- UNIQUE:
{table}_{column}_keyor{table}_{column1}_{column2}_key - FOREIGN KEY:
{table}_{column}_fkey - CHECK:
{table}_{column}_checkor{table}_{description}_check
Named constraints make future migrations predictable:
-- Easy to reference in later migrations
ALTER TABLE users DROP CONSTRAINT users_email_key;