πŸŽ‰ 75% of content is free forever β€” Unlock Premium from $10/mo β†’
CW
Search courses…
πŸ’Ό Servicesℹ️ Aboutβœ‰οΈ ContactView Pricing Plansfrom $10

Entity-Relationship Diagrams

SQL PerformanceER Modeling🟒 Free Lesson

Advertisement

SQL Performance

Entity-Relationship Diagrams

Visualize your database design with entity-relationship diagrams for clearer communication and better architecture.

  • Entities & Attributes β€” Define the core objects and their properties
  • Relationships β€” Map connections between entities with cardinality rules
  • Visual Communication β€” Bridge the gap between developers, DBAs, and stakeholders A picture is worth a thousand rows β€” ER diagrams make database design intuitive.

What is an ER Diagram?

ER diagrams serve as the blueprint for database construction. Before writing a single CREATE TABLE statement, an ER diagram helps you think through the structure, spot design flaws, and communicate with your team.

CUSTOMERSPK customer_idfirst_namelast_nameemailORDERSPK order_idFK customer_idorder_datestatustotalPRODUCTSPK product_idnamepricestock_quantitycategory1 : N1 : NCrow's Foot Notation: ||β€”o{ One-to-Many ||β€”|{ One-to-Required
ER Diagram ComponentSQL EquivalentDescription
EntityTableA thing or concept that stores data
AttributeColumnA property of an entity
Primary KeyPRIMARY KEYUnique identifier for each row
Foreign KeyFOREIGN KEYColumn linking to another table
RelationshipJOIN conditionHow entities relate to each other

Entity Types

-- Entities represented as tables
CREATE TABLE customers (
    customer_id INTEGER PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    email TEXT NOT NULL UNIQUE,
    phone TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE products (
    product_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    description TEXT,
    price DECIMAL(10,2) NOT NULL,
    stock_quantity INTEGER NOT NULL DEFAULT 0,
    category TEXT NOT NULL
);

CREATE TABLE orders (
    order_id INTEGER PRIMARY KEY,
    customer_id INTEGER NOT NULL,
    order_date DATE NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    total DECIMAL(12,2) NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

Strong vs Weak Entities

-- Strong entity: customers
CREATE TABLE customers (
    customer_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

-- Weak entity: customer_addresses (depends on customers)
CREATE TABLE customer_addresses (
    customer_id INTEGER NOT NULL,
    address_type TEXT NOT NULL,  -- Partial key (discriminator)
    street TEXT NOT NULL,
    city TEXT NOT NULL,
    state TEXT NOT NULL,
    zip_code TEXT NOT NULL,
    PRIMARY KEY (customer_id, address_type),
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ON DELETE CASCADE
);

-- Weak entity: order_items (depends on orders)
CREATE TABLE order_items (
    order_id INTEGER NOT NULL,
    line_number INTEGER NOT NULL,  -- Partial key
    product_id INTEGER NOT NULL,
    quantity INTEGER NOT NULL,
    unit_price DECIMAL(10,2) NOT NULL,
    PRIMARY KEY (order_id, line_number),
    FOREIGN KEY (order_id) REFERENCES orders(order_id) ON DELETE CASCADE
);

Relationship Types

Cardinality

CardinalityNotationDescriptionExample
One-to-One (1:1)1 ─── 1Each row in A maps to exactly one row in BPerson ↔ Passport
One-to-Many (1:N)1 ─── NEach row in A maps to many rows in BCustomer β†’ Orders
Many-to-Many (M:N)M ─── NRows in A map to many rows in B, and vice versaStudents ↔ Courses
-- One-to-One relationship
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL UNIQUE
);

CREATE TABLE user_profiles (
    user_id INTEGER PRIMARY KEY,
    bio TEXT,
    avatar_url TEXT,
    theme_preference TEXT DEFAULT 'light',
    FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
);

-- One-to-Many relationship
CREATE TABLE categories (
    category_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE products (
    product_id INTEGER PRIMARY KEY,
    category_id INTEGER NOT NULL,
    name TEXT NOT NULL,
    FOREIGN KEY (category_id) REFERENCES categories(category_id)
);

-- Many-to-Many relationship (junction table)
CREATE TABLE students (
    student_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE courses (
    course_id INTEGER PRIMARY KEY,
    title TEXT NOT NULL
);

CREATE TABLE enrollments (
    student_id INTEGER NOT NULL,
    course_id INTEGER NOT NULL,
    enrolled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    grade TEXT,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES students(student_id) ON DELETE CASCADE,
    FOREIGN KEY (course_id) REFERENCES courses(course_id) ON DELETE CASCADE
);

Participation

-- Total participation: every order MUST have a customer
CREATE TABLE orders (
    order_id INTEGER PRIMARY KEY,
    customer_id INTEGER NOT NULL,  -- NOT NULL enforces total participation
    order_date DATE NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

-- Partial participation: not every customer has a loyalty card
CREATE TABLE loyalty_cards (
    card_id INTEGER PRIMARY KEY,
    customer_id INTEGER NOT NULL UNIQUE,
    points INTEGER DEFAULT 0,
    issued_date DATE NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
    -- customer_id is UNIQUE but could be nullable for partial participation
);

ER Diagram Notation Reference

Chen Notation

SymbolMeaning
RectangleEntity
DiamondRelationship
OvalAttribute
Underlined textPrimary key
Dashed ovalDerived attribute
Double rectangleWeak entity

Crow's Foot Notation (Industry Standard)

SymbolMeaning
`
`o`
`>`
>oOptional many
Single lineTotal participation
Double linePartial participation
-- Crow's Foot notation example:
-- Customer ||--|{ Order : places
-- Order ||--|{ OrderItem : contains
-- Product ||--o{ OrderItem : referenced in

CREATE TABLE customers (
    customer_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE orders (
    order_id INTEGER PRIMARY KEY,
    customer_id INTEGER NOT NULL,
    order_date DATE NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
    -- ||--|{ : Mandatory Many (every order has exactly one customer)
);

CREATE TABLE products (
    product_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE order_items (
    order_item_id INTEGER PRIMARY KEY,
    order_id INTEGER NOT NULL,
    product_id INTEGER NOT NULL,
    quantity INTEGER NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(order_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id)
    -- ||--o{ : Optional Many (product might not be in any orders yet)
);

Real-World ER Design: Hospital Management

-- Entities
CREATE TABLE patients (
    patient_id INTEGER PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    date_of_birth DATE NOT NULL,
    gender TEXT,
    phone TEXT,
    insurance_id TEXT
);

CREATE TABLE doctors (
    doctor_id INTEGER PRIMARY KEY,
    first_name TEXT NOT NULL,
    last_name TEXT NOT NULL,
    specialization TEXT NOT NULL,
    license_number TEXT NOT NULL UNIQUE
);

CREATE TABLE departments (
    department_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    floor_number INTEGER NOT NULL
);

CREATE TABLE appointments (
    appointment_id INTEGER PRIMARY KEY,
    patient_id INTEGER NOT NULL,
    doctor_id INTEGER NOT NULL,
    appointment_date TIMESTAMP NOT NULL,
    reason TEXT,
    status TEXT DEFAULT 'scheduled',
    FOREIGN KEY (patient_id) REFERENCES patients(patient_id),
    FOREIGN KEY (doctor_id) REFERENCES doctors(doctor_id)
);

-- Many-to-Many: doctors belong to departments
CREATE TABLE doctor_departments (
    doctor_id INTEGER NOT NULL,
    department_id INTEGER NOT NULL,
    role TEXT DEFAULT 'member',
    PRIMARY KEY (doctor_id, department_id),
    FOREIGN KEY (doctor_id) REFERENCES doctors(doctor_id),
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

-- Weak entity: medical records depend on patients
CREATE TABLE medical_records (
    patient_id INTEGER NOT NULL,
    record_date TIMESTAMP NOT NULL,
    diagnosis TEXT NOT NULL,
    treatment TEXT,
    notes TEXT,
    doctor_id INTEGER NOT NULL,
    PRIMARY KEY (patient_id, record_date),
    FOREIGN KEY (patient_id) REFERENCES patients(patient_id) ON DELETE CASCADE,
    FOREIGN KEY (doctor_id) REFERENCES doctors(doctor_id)
);

-- One-to-One: patient emergency contact
CREATE TABLE emergency_contacts (
    patient_id INTEGER PRIMARY KEY,
    contact_name TEXT NOT NULL,
    relationship TEXT NOT NULL,
    phone TEXT NOT NULL,
    FOREIGN KEY (patient_id) REFERENCES patients(patient_id) ON DELETE CASCADE
);

ER Design Process

StepActionOutput
1Identify entitiesList of nouns from requirements
2Define attributesProperties for each entity
3Identify relationshipsConnections between entities
4Determine cardinality1:1, 1:N, M:N for each relationship
5Apply normalizationEliminate redundancy
6Review and iterateValidate with stakeholders

Common ER Diagram Mistakes

MistakeProblemSolution
No junction table for M:NViolates 1NF, data integrity issuesCreate intersection entity
Using natural keys everywhereKeys can change, causing cascade updatesUse surrogate keys (UUID, SERIAL)
Over-normalizationExcessive JOINs degrade performanceBalance with denormalization
Missing foreign keysNo referential integrity enforcementAlways declare FOREIGN KEY constraints
Ambiguous relationshipsUnclear business rulesDocument cardinality and participation
-- Bad: Storing multiple values in one column (violates 1NF)
CREATE TABLE products_bad (
    product_id INTEGER PRIMARY KEY,
    tags TEXT  -- "electronics, sale, new" -- BAD!
);

-- Good: Many-to-many with junction table
CREATE TABLE tags (
    tag_id INTEGER PRIMARY KEY,
    name TEXT NOT NULL UNIQUE
);

CREATE TABLE product_tags (
    product_id INTEGER NOT NULL,
    tag_id INTEGER NOT NULL,
    PRIMARY KEY (product_id, tag_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE,
    FOREIGN KEY (tag_id) REFERENCES tags(tag_id) ON DELETE CASCADE
);

Quick Reference: Relationship Patterns

PatternUse CaseImplementation
User ↔ ProfileOne-to-one extensionShared primary key
Customer β†’ OrdersOne-to-many ownershipForeign key in child
Student ↔ CourseMany-to-many enrollmentJunction table
Product β†’ VariantsOne-to-many with discriminatorComposite key on child
Invoice β†’ Line ItemsParent with weak childrenComposite FK + ON DELETE CASCADE

Need Expert SQL Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement