← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Foreign Keys & Referential Integrity

database PHP 5.0+ Intermediate
debt(d5/e5/b7/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5). Missing FK constraints are detectable via mysql-workbench, pgadmin, or laravel-migrations as listed in detection_hints.tools. These are specialist database tools rather than default linters — orphaned records and missing constraints require intentional schema inspection or migration review to identify.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor' (e5). The quick_fix suggests adding FK constraints, but retrofitting them to an existing database with orphaned data requires cleaning up invalid records first, potentially modifying multiple migrations, adding indexes on FK columns, and testing cascade behaviors across the application — this touches multiple files and requires careful coordination.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). Per applies_to, this affects all PHP contexts (web, cli, queue-worker). The absence of FK constraints is a foundational database design choice that shapes how all data operations work — every query, every delete, every migration must account for whether integrity is enforced at the database level. This is load-bearing across the entire system and difficult to change once established.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap / documented gotcha' (t5). The misconception explicitly states developers believe 'ORMs handle referential integrity so FK constraints are redundant.' This is a well-documented gotcha that most experienced developers eventually learn, but it contradicts the intuition that if your ORM handles relationships, the database doesn't need to enforce them. The common_mistakes around CASCADE defaults and missing indexes add additional traps.

About DEBT scoring →

Also Known As

FK referential integrity ON DELETE CASCADE

TL;DR

A foreign key is a column that references the primary key of another table, enforcing referential integrity — no orphaned rows pointing to non-existent parents.

Explanation

Foreign keys enforce that every child row has a corresponding parent row. ON DELETE CASCADE removes children when the parent is deleted. ON DELETE RESTRICT (default in PostgreSQL) blocks deletion if children exist. ON DELETE SET NULL nullifies the FK column. Foreign keys also create implicit indexes in MySQL but not PostgreSQL — you must add them explicitly. Many applications disable FK constraints for performance and rely on application-level validation, which always drifts.

Diagram

flowchart TD
    USERS[(users<br/>id PK)]
    ORDERS[(orders<br/>id PK<br/>user_id FK)]
    ITEMS[(order_items<br/>id PK<br/>order_id FK)]
    USERS -->|ON DELETE RESTRICT| ORDERS
    ORDERS -->|ON DELETE CASCADE| ITEMS
    BAD[DELETE user 42] -->|blocked| USERS
    note1[FK prevents orphaned<br/>orders referencing<br/>deleted user]
style USERS fill:#1f6feb,color:#fff
style ORDERS fill:#238636,color:#fff
style ITEMS fill:#238636,color:#fff

Common Misconception

ORMs handle referential integrity so FK constraints are redundant — application code has bugs; the database constraint is the last reliable safety net.

Why It Matters

Without FK constraints, a deleted user leaves orphaned orders, comments, and settings that accumulate silently — queries return null joins and application code crashes unpredictably.

Common Mistakes

  • Not adding an index on the FK column in PostgreSQL — joins and cascade operations do full table scans without it.
  • Using ON DELETE CASCADE everywhere without considering whether child records should survive parent deletion.
  • Disabling FK checks during bulk imports and forgetting to re-enable them — orphaned rows persist permanently.
  • Not specifying ON DELETE behaviour — defaults differ between MySQL (RESTRICT) and other databases.

Code Examples

✗ Vulnerable
-- No FK constraint — orphaned rows accumulate silently:
CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT  -- No FK: user deleted, orders remain with dangling user_id
);
-- DELETE FROM users WHERE id = 42;
-- orders still has rows with user_id = 42 — silent data corruption
✓ Fixed
-- FK with explicit delete behaviour:
CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT NOT NULL
        REFERENCES users(id)
        ON DELETE RESTRICT   -- Block user deletion if orders exist
);
-- PostgreSQL: also add index
CREATE INDEX idx_orders_user_id ON orders(user_id);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 31
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 1 ping T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S
No pings yet today
Perplexity 8 Amazonbot 7 Unknown AI 4 Ahrefs 2 ChatGPT 2 Google 2 Majestic 1
crawler 23 crawler_json 1 pre-tracking 2
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Always define foreign key constraints — they prevent orphaned records at the database level regardless of what application code does; add indexes on FK columns for JOIN performance
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Integer columns referencing another table's ID without FK constraint; orphaned records in database; no indexes on FK columns
Auto-detectable: ✓ Yes mysql-workbench pgadmin laravel-migrations
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update
CWE-1284

✓ schema.org compliant