Managing Database Constraints

1. Understanding Constraint Types

ConstraintEnforces
NOT NULLMandatory value
UNIQUENo duplicate values
PRIMARY KEYUNIQUE + NOT NULL row identifier
FOREIGN KEYReferential integrity
CHECKBoolean validation rule
EXCLUSION (Postgres)No two rows match operator (e.g., overlapping ranges)
DEFAULTAuto value when omitted (not strictly a constraint)

2. Creating Named Constraints

PatternExample
InlineCONSTRAINT chk_price CHECK (price > 0)
Table-levelCONSTRAINT uq_email UNIQUE(email)
Naming conventionpk_/fk_/uq_/chk_/idx_ prefixes
Note: Always name constraints — auto-generated names make migrations and error messages opaque.

3. Implementing Referential Integrity

ActionBehavior
ON DELETE CASCADEDelete child rows automatically
ON DELETE SET NULLNullify child FK
ON DELETE RESTRICTPrevent parent delete if children exist
ON UPDATE CASCADEPropagate PK changes (rarely needed with surrogate keys)
MATCH FULL / SIMPLEHow NULL FK columns are treated

4. Deferring Constraint Checking

ModeBehavior
NOT DEFERRABLE (default)Checked per statement
DEFERRABLE INITIALLY IMMEDIATEPer-statement, but can defer per tx
DEFERRABLE INITIALLY DEFERREDChecked at COMMIT
SET CONSTRAINTS ALL DEFERREDDefer all in current tx

Example: Circular FK with Deferral

BEGIN;
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO a(id, b_id) VALUES (1, 1);
INSERT INTO b(id, a_id) VALUES (1, 1);
COMMIT;

5. Implementing Domain Constraints

MechanismExample
DOMAIN typeCREATE DOMAIN age_t AS INT CHECK (VALUE BETWEEN 0 AND 150);
ENUM typeCREATE TYPE color AS ENUM ('red','green','blue');
CHECK with regexCHECK (phone ~ '^\+\d{8,15}$')
Lookup table + FKMost flexible — supports dynamic values

6. Using Cascading Actions

ScenarioRecommended Action
Order → OrderItemsCASCADE (items meaningless without order)
User → PostsSET NULL or soft-delete (preserve content)
Category → ProductsRESTRICT (don't lose products silently)
Audit logsNO ACTION (never cascade-delete history)

7. Implementing Business Rule Constraints

MechanismUse Case
CHECKSingle-row rules (price > 0)
EXCLUSION constraintNo overlapping bookings: EXCLUDE USING gist (room WITH =, when WITH &&)
TriggerMulti-row/multi-table invariants
Stored procedure + txComplex workflows, atomic enforcement
Application layerRules requiring external data

8. Handling Constraint Violations

SQLSTATEMeaning
23502NOT NULL violation
23503Foreign key violation
23505Unique violation
23514Check violation
23P01Exclusion violation

Example: ON CONFLICT (Postgres UPSERT)

INSERT INTO users(email, name) VALUES ('a@x.com','Ann')
ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name;

9. Disabling and Enabling Constraints

OperationSQL
Postgres FKALTER TABLE t DISABLE TRIGGER ALL; (FK is via trigger)
MySQL FKSET FOREIGN_KEY_CHECKS = 0;
OracleALTER TABLE t DISABLE CONSTRAINT name;
SQL ServerALTER TABLE t NOCHECK CONSTRAINT name;
Validate laterALTER TABLE t VALIDATE CONSTRAINT name;
Warning: Disabling constraints during bulk loads is faster, but always re-validate before resuming traffic — corrupt data is much worse than slow loads.

10. Documenting Constraint Business Rules

DocumentationContent
COMMENT ON CONSTRAINTInline DB comment
Schema docs (SchemaSpy)Auto-generated reference
ADR + business glossaryRationale + owners
Naming conventionEmbed intent (chk_age_nonneg)