0
0
PostgresqlHow-ToBeginner · 3 min read

How to Use Deferrable Constraint in PostgreSQL: Syntax and Examples

In PostgreSQL, you use DEFERRABLE constraints to delay the enforcement of foreign key or unique constraints until the end of a transaction. You define a constraint as DEFERRABLE INITIALLY DEFERRED or DEFERRABLE INITIALLY IMMEDIATE to control when the checks occur, allowing temporary violations inside transactions.
📐

Syntax

The DEFERRABLE constraint allows you to specify when PostgreSQL should check the constraint during a transaction. You can use:

  • DEFERRABLE INITIALLY IMMEDIATE: Checks the constraint immediately after each statement.
  • DEFERRABLE INITIALLY DEFERRED: Checks the constraint only at the end of the transaction.
  • NOT DEFERRABLE: The constraint is always checked immediately (default).

This is useful for foreign keys or unique constraints that might be temporarily violated during a transaction but must be valid at commit.

sql
CREATE TABLE child_table (
  id SERIAL PRIMARY KEY,
  parent_id INT,
  CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES parent_table(id)
    DEFERRABLE INITIALLY DEFERRED
);
💻

Example

This example shows how to create two tables with a deferrable foreign key constraint and how to defer constraint checks inside a transaction.

sql
CREATE TABLE parent_table (
  id SERIAL PRIMARY KEY
);

CREATE TABLE child_table (
  id SERIAL PRIMARY KEY,
  parent_id INT,
  CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES parent_table(id)
    DEFERRABLE INITIALLY DEFERRED
);

BEGIN;
-- Insert child referencing a parent that does not exist yet
INSERT INTO child_table (parent_id) VALUES (1);
-- Insert the parent after
INSERT INTO parent_table DEFAULT VALUES;
COMMIT;
Output
BEGIN INSERT 0 1 INSERT 0 1 COMMIT
⚠️

Common Pitfalls

Common mistakes when using deferrable constraints include:

  • Not declaring the constraint as DEFERRABLE, so you cannot defer it in transactions.
  • Assuming constraints are deferred by default; they are NOT DEFERRABLE unless specified.
  • Trying to defer constraints outside a transaction block; deferring only works inside BEGIN ... COMMIT.

Always check if your constraint is declared DEFERRABLE before using SET CONSTRAINTS commands.

sql
/* Wrong: constraint not deferrable, so this fails */
CREATE TABLE child_table (
  id SERIAL PRIMARY KEY,
  parent_id INT,
  CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES parent_table(id)
    NOT DEFERRABLE
);

BEGIN;
SET CONSTRAINTS fk_parent DEFERRED; -- ERROR: constraint is not deferrable
COMMIT;
Output
ERROR: constraint "fk_parent" is not deferrable
📊

Quick Reference

KeywordMeaning
DEFERRABLEConstraint can be deferred until transaction end
NOT DEFERRABLEConstraint checked immediately after each statement
INITIALLY IMMEDIATEDefault check timing, constraint checked after each statement
INITIALLY DEFERREDConstraint check delayed until transaction commit
SET CONSTRAINTS ... DEFERREDCommand to defer constraint checks inside a transaction
SET CONSTRAINTS ... IMMEDIATECommand to enforce constraint checks immediately inside a transaction

Key Takeaways

Declare constraints as DEFERRABLE to allow deferring their checks inside transactions.
Use INITIALLY DEFERRED to delay constraint checks until transaction commit.
Deferring constraints only works inside explicit transaction blocks (BEGIN...COMMIT).
Attempting to defer NOT DEFERRABLE constraints causes errors.
Use SET CONSTRAINTS command to control constraint checking timing during transactions.