ER Model in DBMS Explained — Entities, Attributes, and Relationships
ER Model in DBMS explained from scratch — entities, attributes, relationships, cardinality, and how to draw your first ER diagram with real-world examples.
N
Naren · Founder
Plain-English first. Then code. Then the interview question.
ER Model is a conceptual framework for designing database schemas visually before writing SQL
Entities (rectangles) represent real-world objects; Attributes (ovals) describe them
Relationships (diamonds) connect entities with cardinality (1:1, 1:N, M:N)
Performance insight: Getting cardinality wrong leads to costly schema redesigns that take weeks
Production insight: Inconsistent relationship participation can cause orphaned data or NULL constraint violations
Biggest mistake: Treating M:N relationships as directly storable instead of creating a junction table
Plain-English First
Imagine you're building a school's record system on paper before touching any computer. You'd first sketch out: 'What are the THINGS I need to track?' (students, teachers, classes), 'What do I know ABOUT each thing?' (a student has a name, age, ID), and 'How do these things CONNECT?' (a student ENROLLS IN a class). That sketch — those boxes, bubbles, and lines — is literally an ER diagram. The ER Model is just the rulebook for drawing that sketch in a way every database designer on the planet understands.
Every app you've used — Instagram, your bank's website, your school's portal — stores data somewhere. Before a single line of code is written, a database designer sits down and asks: 'What exactly am I storing, and how does it all fit together?' Get that wrong and you're rebuilding the entire database six months later. The ER Model exists precisely to prevent that painful, expensive mistake.
The Entity-Relationship Model, introduced by Dr. Peter Chen in 1976, gives you a visual language to plan a database at a high level — before you worry about tables, SQL, or any specific database software. It's like an architect drawing blueprints before construction begins. You wouldn't build a house without blueprints, and you shouldn't build a database without an ER diagram.
By the end of this article you'll be able to identify entities, attributes, and relationships in any real-world scenario, understand the rules around cardinality and participation, read and draw a basic ER diagram from scratch, and confidently explain all of this in a technical interview. Let's build it up piece by piece.
Entities and Attributes — The 'Things' and Their 'Details'
An entity is any real-world object or concept that you need to store data about and that can be uniquely identified. In a university system, STUDENT, COURSE, and PROFESSOR are all entities. Think of an entity like a category — not a specific student named 'Alice', but the concept of 'a student' in general.
An entity instance is one specific member of that category. Alice (Student ID: 101) is an instance. Bob (Student ID: 102) is another instance.
Attributes are the properties or details that describe an entity. A STUDENT entity might have attributes: StudentID, FirstName, LastName, DateOfBirth, and Email. In an ER diagram, entities are drawn as rectangles and attributes as ovals connected to their entity by a line.
Attributes come in important flavours you need to know. A simple attribute stores a single value (like Age). A composite attribute is made of smaller parts — FullName can be split into FirstName and LastName. A multi-valued attribute can hold more than one value — a student can have multiple PhoneNumbers. A derived attribute is calculated from another — Age can be derived from DateOfBirth, so it's drawn with a dashed oval.
The key attribute uniquely identifies each entity instance. StudentID is a key attribute — no two students share it. In diagrams, key attributes are underlined.
university_entities.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
-- ============================================================-- Translating ER Entities and Attributes into real SQL tables-- Using io_thecodeforge schema for production naming-- ============================================================-- ENTITY: Student-- KEY ATTRIBUTE: student_id (underlined in ER diagram -- must be unique)-- SIMPLE ATTRS: first_name, last_name, email-- DERIVED ATTR: age (we store date_of_birth and calculate age when needed)-- COMPOSITE ATTR: full_name is split into first_name + last_name-- MULTI-VALUED: phone_numbers gets its OWN separate table (shown below)CREATETABLE io_thecodeforge.Student (
student_id INTPRIMARYKEY,
first_name VARCHAR(50) NOTNULL,
last_name VARCHAR(50) NOTNULL,
date_of_birth DATENOTNULL,
email VARCHAR(100) UNIQUENOTNULL
);
-- Multi-valued attribute 'PhoneNumbers' becomes its own table.CREATETABLE io_thecodeforge.StudentPhone (
phone_id INTPRIMARYKEY,
student_id INTNOTNULL,
phone_number VARCHAR(15) NOTNULL,
FOREIGNKEY (student_id) REFERENCES io_thecodeforge.Student(student_id)
);
-- ENTITY: CourseCREATETABLE io_thecodeforge.Course (
course_id INTPRIMARYKEY,
course_name VARCHAR(100) NOTNULL,
credits INTNOTNULL
);
-- Insert sample dataINSERTINTO io_thecodeforge.StudentVALUES (101, 'Alice', 'Morgan', '2001-04-15', 'alice@uni.edu');
INSERTINTO io_thecodeforge.StudentVALUES (102, 'Bob', 'Chen', '2000-09-22', 'bob@uni.edu');
INSERTINTO io_thecodeforge.StudentPhoneVALUES (1, 101, '555-0101');
INSERTINTO io_thecodeforge.StudentPhoneVALUES (2, 101, '555-0202');
INSERTINTO io_thecodeforge.StudentPhoneVALUES (3, 102, '555-0303');
INSERTINTO io_thecodeforge.CourseVALUES (1, 'Database Systems', 3);
INSERTINTO io_thecodeforge.CourseVALUES (2, 'Data Structures', 4);
-- Query to see Alice's full record including derived ageSELECT
student_id,
first_name || ' ' || last_name AS full_name,
EXTRACT(YEARFROMAGE(date_of_birth)) AS age,
email
FROM io_thecodeforge.StudentWHERE student_id = 101;
In ER diagrams you underline the key attribute. In the actual database table this becomes the PRIMARY KEY constraint. They represent the same concept at different stages — ER diagram is the plan, the SQL table is the built result. Interviewers love asking this distinction.
Production Insight
Overloading an entity with too many attributes creates wide tables that hit row size limits and slow scans.
Storing derived attributes instead of base data causes stale values and recalculation bugs.
Rule: Store raw data; derive computed values at query time.
Key Takeaway
Entities map to tables; attributes map to columns.
Composite attributes split into multiple columns; multi-valued attributes become separate tables.
Never store derived attributes — compute them on the fly.
Relationships and Cardinality — How Entities Connect to Each Other
Entities don't exist in isolation — they interact. A STUDENT enrolls in a COURSE. A PROFESSOR teaches a COURSE. These interactions are relationships, and in ER diagrams they're drawn as diamonds connecting two or more entity rectangles.
Relationships also have attributes. The ENROLLS_IN relationship between STUDENT and COURSE might have an EnrollmentDate attribute — that date doesn't belong to the student alone or the course alone, it belongs to the act of enrolling.
Cardinality is the most critical concept in ER modeling. It defines HOW MANY instances of one entity can relate to how many instances of another. There are three types.
One-to-One (1:1): One entity instance links to exactly one instance on the other side. A PERSON has exactly one PASSPORT. One passport belongs to exactly one person.
One-to-Many (1:N): One instance on side A relates to many instances on side B, but each instance on side B relates to only one on side A. One PROFESSOR teaches many COURSES, but each course is taught by one professor.
Many-to-Many (M:N): Many instances on side A relate to many on side B. A STUDENT can enroll in many COURSES, and a COURSE can have many STUDENTS enrolled.
Participation constraints tell you whether participation is mandatory. Total participation (double line) means every instance MUST participate. Partial participation (single line) means it's optional.
university_relationships.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
-- ============================================================-- Translating ER Relationships and Cardinality into SQL-- ============================================================-- Relationship: PROFESSOR teaches COURSE (One-to-Many)-- We implement 1:N by placing the foreign key on the 'many' side (Course table)CREATETABLE io_thecodeforge.Professor (
professor_id INTPRIMARYKEY,
full_name VARCHAR(100) NOTNULL,
department VARCHAR(50) NOTNULL
);
ALTERTABLE io_thecodeforge.CourseADDCOLUMN professor_id INT,
ADDCONSTRAINT fk_course_professor
FOREIGNKEY (professor_id) REFERENCES io_thecodeforge.Professor(professor_id);
-- Relationship: STUDENT enrolls in COURSE (Many-to-Many)-- M:N relationships ALWAYS become their own 'junction' tableCREATETABLE io_thecodeforge.Enrollment (
enrollment_id INTPRIMARYKEY,
student_id INTNOTNULL,
course_id INTNOTNULL,
enrollment_date DATENOTNULL,
grade CHAR(2),
FOREIGNKEY (student_id) REFERENCES io_thecodeforge.Student(student_id),
FOREIGNKEY (course_id) REFERENCES io_thecodeforge.Course(course_id),
UNIQUE (student_id, course_id)
);
-- Relationship: PERSON has PASSPORT (One-to-One)-- UNIQUE foreign key enforces 1:1CREATETABLE io_thecodeforge.Person (
person_id INTPRIMARYKEY,
full_name VARCHAR(100) NOTNULL
);
CREATETABLE io_thecodeforge.Passport (
passport_id INTPRIMARYKEY,
passport_number VARCHAR(20) UNIQUENOTNULL,
person_id INTUNIQUENOTNULL,
expiry_date DATENOTNULL,
FOREIGNKEY (person_id) REFERENCES io_thecodeforge.Person(person_id)
);
-- Sample dataINSERTINTO io_thecodeforge.ProfessorVALUES (1, 'Dr. Sarah Hill', 'Computer Science');
INSERTINTO io_thecodeforge.ProfessorVALUES (2, 'Dr. James Okafor','Mathematics');
UPDATE io_thecodeforge.CourseSET professor_id = 1WHERE course_id = 1;
UPDATE io_thecodeforge.CourseSET professor_id = 1WHERE course_id = 2;
INSERTINTO io_thecodeforge.EnrollmentVALUES (1, 101, 1, '2024-01-10', 'A');
INSERTINTO io_thecodeforge.EnrollmentVALUES (2, 101, 2, '2024-01-10', 'B+');
INSERTINTO io_thecodeforge.EnrollmentVALUES (3, 102, 1, '2024-01-11', NULL);
-- Query: Alice's courses with gradesSELECT
s.first_name || ' ' || s.last_name AS student_name,
c.course_name,
e.enrollment_date,
COALESCE(e.grade, 'Not graded') AS grade
FROM io_thecodeforge.Enrollment e
JOIN io_thecodeforge.Student s ON e.student_id = s.student_id
JOIN io_thecodeforge.Course c ON e.course_id = c.course_id
WHERE e.student_id = 101ORDERBY c.course_name;
Watch Out: M:N Relationships Don't Map Directly to Tables
A Many-to-Many relationship in an ER diagram can never be directly stored as-is in a relational database. You MUST create a junction table (also called a bridge table or associative entity) that holds foreign keys from both sides. Forgetting this is one of the most common beginner database design mistakes.
Production Insight
One-to-Many relationships cause the most foreign key mistakes — putting the FK on the wrong side breaks referential integrity.
Many-to-Many without a junction table creates duplicate data and query nightmares.
Rule: For 1:N, FK goes on the 'N' side; for M:N, always create a junction table.
Key Takeaway
Cardinality drives FK placement.
1:1 uses UNIQUE FK on either side.
1:N uses FK on the many side.
M:N requires a junction table with composite PK.
Weak Entities, Specialisation, and the Full ER Diagram Picture
Most real systems have an important special case: a weak entity. A weak entity is one that cannot be uniquely identified by its own attributes alone — it depends on another entity (its owner entity) to be identified.
Think of ORDER_ITEM. An order item has an item number (item 1, item 2, item 3...), but that number only makes sense WITHIN a specific ORDER. Item 3 of Order #500 is completely different from item 3 of Order #501. ORDER_ITEM depends on ORDER for its identity. In ER diagrams, weak entities use double rectangles, and the relationship connecting them to their owner uses a double diamond.
The partial key of a weak entity (the attribute that identifies it within its owner) is shown with a dashed underline rather than a solid one.
Specialisation and Generalisation add inheritance-like thinking. Suppose you have a PERSON entity. An EMPLOYEE and a STUDENT are both persons but have extra specific attributes. You can generalise EMPLOYEE and STUDENT into PERSON (they share common attributes like Name, Age), and specialise PERSON into the subtypes. This is identical to how class inheritance works in object-oriented programming. In ER diagrams this is drawn as a triangle labelled 'ISA'.
With all these building blocks — entities, attributes, relationships, cardinality, weak entities, and specialisation — you can model virtually any real-world system before writing a single line of SQL.
weak_entity_and_specialisation.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
-- ============================================================-- Weak Entity: ORDER_ITEM depends on ORDER for its identity-- Specialisation: EMPLOYEE and STUDENT are subtypes of PERSON-- ============================================================-- Strong entity: ORDERCREATETABLE io_thecodeforge.CustomerOrder (
order_id INTPRIMARYKEY,
order_date DATENOTNULL,
customer_name VARCHAR(100) NOTNULL
);
-- Weak entity: ORDER_ITEM-- item_number is the PARTIAL KEYCREATETABLE io_thecodeforge.OrderItem (
order_id INTNOTNULL,
item_number INTNOTNULL,
product_name VARCHAR(100) NOTNULL,
quantity INTNOTNULL,
unit_price DECIMAL(8,2) NOTNULL,
PRIMARYKEY (order_id, item_number),
FOREIGNKEY (order_id) REFERENCES io_thecodeforge.CustomerOrder(order_id)
ONDELETECASCADE
);
-- Specialisation / GeneralisationCREATETABLE io_thecodeforge.Person (
person_id INTPRIMARYKEY,
full_name VARCHAR(100) NOTNULL,
date_of_birth DATENOTNULL,
email VARCHAR(100) UNIQUENOTNULL
);
CREATETABLE io_thecodeforge.Employee (
person_id INTPRIMARYKEY,
employee_code VARCHAR(20) UNIQUENOTNULL,
hire_date DATENOTNULL,
salary DECIMAL(10,2) NOTNULL,
FOREIGNKEY (person_id) REFERENCES io_thecodeforge.Person(person_id)
);
CREATETABLE io_thecodeforge.Student_Person (
person_id INTPRIMARYKEY,
student_id VARCHAR(20) UNIQUENOTNULL,
enrollment_year INTNOTNULL,
major VARCHAR(50),
FOREIGNKEY (person_id) REFERENCES io_thecodeforge.Person(person_id)
);
-- Sample dataINSERTINTO io_thecodeforge.CustomerOrderVALUES (500, '2024-03-01', 'Greenleaf Supplies');
INSERTINTO io_thecodeforge.CustomerOrderVALUES (501, '2024-03-02', 'BlueStar Corp');
INSERTINTO io_thecodeforge.OrderItemVALUES (500, 1, 'Printer Paper A4', 10, 5.99);
INSERTINTO io_thecodeforge.OrderItemVALUES (500, 2, 'Black Ink Cartridge', 3, 18.50);
INSERTINTO io_thecodeforge.OrderItemVALUES (500, 3, 'Stapler', 1, 12.00);
INSERTINTO io_thecodeforge.OrderItemVALUES (501, 1, 'Whiteboard Markers', 5, 3.25);
INSERTINTO io_thecodeforge.PersonVALUES (1, 'Carol White', '1985-07-20', 'carol@company.com');
INSERTINTO io_thecodeforge.EmployeeVALUES (1, 'EMP-00421', '2015-03-01', 72000.00);
-- Retrieve a full order with line itemsSELECT
o.order_id,
o.customer_name,
i.item_number,
i.product_name,
i.quantity,
i.unit_price,
(i.quantity * i.unit_price) AS line_total
FROM io_thecodeforge.CustomerOrder o
JOIN io_thecodeforge.OrderItem i ON o.order_id = i.order_id
WHERE o.order_id = 500ORDERBY i.item_number;
Interviewers frequently ask 'Can you give an example of a weak entity?' The ORDER_ITEM example is perfect. Follow it up by explaining that a weak entity's primary key in SQL is always a composite key combining the owner's primary key with the partial key — never just the partial key alone.
Production Insight
Weak entities without ON DELETE CASCADE accumulate orphaned data that bloats storage and skews analytics.
Specialisation subtypes missing the FK to the parent entity break the ISA relationship.
Rule: Weak entity's PK must be composite; use ON DELETE CASCADE.
Key Takeaway
Weak entity identity = owner PK + partial key.
Specialisation maps to separate tables with shared PK.
Always cascade deletes from owner to weak entity.
Drawing an ER Diagram from a Real Scenario: The Library System
Let's apply everything to a concrete system: a library. You need to track books, members, and loans.
First, identify the entities. BOOK, MEMBER, and LOAN are clear. But don't stop there — a library may have multiple copies of the same book, so you need BOOK_COPY. Each loan can include multiple copies? No, each loan is for one copy at a time, but a member can borrow many copies over time. So the relationship is MEMBER borrows BOOK_COPY. But a BOOK has many copies, and a copy belongs to one book.
Now relationships: BOOK has many BOOK_COPY (1:N). MEMBER borrows many BOOK_COPY (1:N) — each loan is for one copy, but a member can have multiple active loans. LOAN links MEMBER and BOOK_COPY? Actually a loan is a relationship between MEMBER and BOOK_COPY with attributes (LoanDate, etc). That's a M:N relationship between MEMBER and BOOK_COPY resolved into the LOAN entity (associative entity). So LOAN is both an entity (has its own key) and a relationship.
Cardinalities: A member can have many loans (1:N from MEMBER to LOAN). A book copy can be in many loans over time (1:N from BOOK_COPY to LOAN). But a loan involves exactly one member and one copy. So it's a M:N between MEMBER and BOOK_COPY with extra attributes, often modeled as an associative entity.
Weak entity? Not in this simple model, but if we wanted to track loan items separately, we could. Alternatively, BOOK_COPY is a weak entity dependent on BOOK because CopyID only unique per book.
Now draw the diagram: rectangles for BOOK, BOOK_COPY, MEMBER, LOAN. Ovals for attributes. Diamonds for relationships: BOOK-HAS-BOOK_COPY, MEMBER-borrows-BOOK_COPY via LOAN? Actually LOAN is the relationship entity. Connect MEMBER to LOAN and BOOK_COPY to LOAN.
Specialisation: Maybe MEMBER can be STUDENT_MEMBER or FACULTY_MEMBER with different borrowing limits. Could add an ISA triangle.
This exercise shows how a seemingly simple system reveals entities, weak entities, and relationship entities once you think deeply.
Alice Morgan | Effective Java | 2024-04-01 | 2024-04-15
Pro Tip: Spotting Entities vs Attributes
If something has its own attributes or can be related to multiple other entities, it's an entity, not an attribute. For example, 'ShelfLocation' on BookCopy is an attribute, but if you need to track shelf capacity or floor, then 'Shelf' becomes its own entity.
Production Insight
Treating book copies as attributes of Book (e.g., a list of copy IDs in a JSON column) makes it impossible to track individual copy history or condition.
Rule: When an object exists independently and has its own lifecycle, make it an entity, not an attribute.
Key Takeaway
Real-world systems reveal entities, weak entities, and relationship entities.
Always look for 'thing vs. property' — if it has properties or relationships, it's an entity.
Practice with familiar domains to internalise the pattern.
From ER Diagram to Relational Schema: The Transformation Rules
Once your ER diagram is complete, you need to transform it into a relational schema. This is a systematic process with well-defined rules.
Rule 1: Each regular entity becomes a table. The key attribute becomes the PRIMARY KEY.
Rule 2: Each composite attribute is split into its component attributes as separate columns.
Rule 3: Each multi-valued attribute becomes a separate table with a foreign key to the original entity's table and the attribute value column. The primary key is typically a composite of the foreign key and a unique value.
Rule 4: Each weak entity becomes a table with a composite primary key: the primary key of the owner entity plus the weak entity's partial key. Include a foreign key to the owner table with ON DELETE CASCADE.
Rule 5: For a 1:1 relationship, add a foreign key in one of the tables (preferably the one with total participation) and make it UNIQUE.
Rule 6: For a 1:N relationship, add a foreign key in the table representing the 'N' side referencing the '1' side.
Rule 7: For an M:N relationship, create a junction table with foreign keys to both entity tables. The primary key is a composite of those two foreign keys (or include a surrogate key if relationship attributes exist).
Rule 8: For specialisation (ISA), create a table for the superclass with its primary key. For each subclass, create a table with the same primary key (shared primary key) and additional attributes. Add foreign key from subclass to superclass.
These rules guarantee a lossless and standardised translation from conceptual model to physical schema.
transformation_rules.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
-- ============================================================-- Summary: ER to Relational Transformation Rules-- Each rule corresponds to a specific ER construct-- ============================================================-- Rule 1: Entity -> Table, Key attribute -> PKCREATETABLE io_thecodeforge.EntityTable (
entity_id INTPRIMARYKEY, -- Key attribute
attr1 VARCHAR(100),
attr2 VARCHAR(100)
);
-- Rule 2: Composite attribute -> multiple columns-- Already done above: Person (full_name split into first_name, last_name)-- Rule 3: Multi-valued attribute -> separate table with FKCREATETABLE io_thecodeforge.MultiValued (
entity_id INTNOTNULL,
value_id INTNOTNULL, -- Partial key or surrogate
value VARCHAR(100) NOTNULL,
PRIMARYKEY (entity_id, value_id),
FOREIGNKEY (entity_id) REFERENCES io_thecodeforge.EntityTable(entity_id)
);
-- Rule 4: Weak entity -> composite PK-- Already done: OrderItem (order_id, item_number)-- Rule 5: 1:1 relationship -> UNIQUE FK (shown in Person/Passport)-- Rule 6: 1:N relationship -> FK on N side (shown in Professor/Course)-- Rule 7: M:N relationship -> junction table (shown in Enrollment)-- Rule 8: Specialisation -> shared PK (shown in Person/Employee)-- Example: Applying all rules to a university schema-- This single script creates a full schema from an ER diagramCREATETABLE io_thecodeforge.Department (
dept_id INTPRIMARYKEY,
name VARCHAR(100) NOTNULL
);
CREATETABLE io_thecodeforge.Professor (
prof_id INTPRIMARYKEY,
name VARCHAR(100) NOTNULL,
dept_id INTNOTNULL,
FOREIGNKEY (dept_id) REFERENCES io_thecodeforge.Department(dept_id) -- 1:N: many professors in one department
);
CREATETABLE io_thecodeforge.Course (
course_id INTPRIMARYKEY,
title VARCHAR(200) NOTNULL,
credits INTNOTNULL,
prof_id INTNOTNULL,
FOREIGNKEY (prof_id) REFERENCES io_thecodeforge.Professor(prof_id) -- 1:N: one professor teaches many courses
);
CREATETABLE io_thecodeforge.Student (
student_id INTPRIMARYKEY,
name VARCHAR(100) NOTNULL,
email VARCHAR(100) UNIQUENOTNULL
);
-- M:N: many students enroll in many courses -> junction tableCREATETABLE io_thecodeforge.Enrollment (
enrollment_id INTPRIMARYKEY,
student_id INTNOTNULL,
course_id INTNOTNULL,
grade CHAR(2),
semester VARCHAR(10) NOTNULL,
FOREIGNKEY (student_id) REFERENCES io_thecodeforge.Student(student_id),
FOREIGNKEY (course_id) REFERENCES io_thecodeforge.Course(course_id),
UNIQUE (student_id, course_id, semester) -- a student can enroll in same course only once per semester
);
Output
-- Success: No errors, schema created.
Mental Model: The Assembly Line
Entity → Table: The raw material becomes a container.
Attribute → Column: Each property gets a slot in the container.
Relationship → Foreign Key or Junction Table: Connections between containers are modeled through references.
Weak Entity → Composite Key: Dependencies are captured by combining identifiers.
Specialisation → Shared PK: Inheritance is modeled by using the same primary key in multiple tables.
Production Insight
Skipping the transformation step leads to a schema that doesn't match the intended relationships.
Without explicit rules, developers might place foreign keys arbitrarily, breaking referential integrity.
Rule: Always apply the rules mechanically — don't guess where FK should go.
Key Takeaway
ER diagram is the blueprint; transformation rules are the assembly instructions.
Follow rules 1-8 in order for a lossless translation.
A correct transformation eliminates most design errors before you write a single INSERT.
● Production incidentPOST-MORTEMseverity: high
The Missing Junction Table That Cost $50,000 in Lost Revenue
Symptom
The revenue dashboard showed inconsistent totals. Some orders reported zero revenue, others were double-counting products. The inventory system showed products out of stock even though only one unit was sold.
Assumption
The team assumed that an order could contain multiple products but thought they could store product IDs directly in a single column using a JSON array. They believed it would simplify the schema.
Root cause
The ER diagram they drew initially showed a Many-to-Many relationship between ORDER and PRODUCT, but during implementation they skipped the junction table. They used a simple array column for product IDs, which broke normalization, made queries impossible to optimize, and allowed data corruption (duplicate entries, missing products).
Fix
They reverted the schema: created a proper ORDER_ITEM table with composite primary key (order_id, product_id), added quantity and price at the time of order, and migrated the existing six months of data using a script that parsed the old JSON arrays. They also added foreign key constraints and a unique constraint on (order_id, product_id).
Key lesson
Never shortcut a Many-to-Many relationship — a junction table is mandatory.
An ER diagram is cheap insurance; skipping it leads to costly rework.
If data looks like it belongs in a comma-separated list, stop and create a separate table.
Production debug guideDiagnose common schema issues rooted in ER model mistakes5 entries
Symptom · 01
Duplicate rows in what should be a unique relationship
→
Fix
Check if you forgot a UNIQUE constraint on the composite foreign keys. In ER terms, your relationship's cardinality is not enforced.
Symptom · 02
Slow queries that join many tables with no index hits
→
Fix
Verify that all foreign keys have indexes. In ER terms, relationships become FK columns — those columns need indexing for joins.
Symptom · 03
Unable to delete a parent record due to foreign key constraint
→
Fix
Check if you used ON DELETE CASCADE. In ER terms, if the relationship has total participation from the child (weak entity), you must cascade delete.
Symptom · 04
Data redundancy: same customer name stored in multiple orders
→
Fix
Promote 'Customer' from an attribute of Order to its own entity. In ER terms, any concept that appears repeatedly should be an entity, not an attribute.
Symptom · 05
Many NULL columns in a table that should be in separate subtypes
→
Fix
Check if you merged specialisation into a single table. In ER terms, each subclass should be its own table with shared PK.
★ ER Design Quick FixesImmediate checks when your database schema doesn't match the intended ER model
Rows in a 'weak' table without a parent−
Immediate action
Check for missing ON DELETE CASCADE or orphaned rows.
Commands
SELECT * FROM io_thecodeforge.OrderItem WHERE order_id NOT IN (SELECT order_id FROM io_thecodeforge.CustomerOrder);
SELECT COUNT(*) FROM io_thecodeforge.OrderItem WHERE order_id IS NULL;
Fix now
Add ON DELETE CASCADE to the foreign key and delete orphans with a DELETE JOIN.
Duplicate entries in a junction table+
Immediate action
Check for missing UNIQUE constraint on the composite FK.
Commands
SELECT student_id, course_id, COUNT(*) FROM io_thecodeforge.Enrollment GROUP BY student_id, course_id HAVING COUNT(*) > 1;
SHOW CREATE TABLE io_thecodeforge.Enrollment;
Fix now
Add UNIQUE (student_id, course_id) and deduplicate by keeping the earliest row.
Table with way too many columns (wide table)+
Immediate action
Identify which columns should be separate entities or multi-valued attributes.
Commands
SELECT COUNT(*) FROM information_schema.columns WHERE table_name = 'YourTable';
Check for patterns like phone1, phone2, phone3 columns.
Fix now
Create a dependent table for multi-valued attributes and move columns there.
Identify all foreign keys that should exist but don't.
Commands
SELECT table_name, column_name FROM information_schema.columns WHERE column_name LIKE '%_id' AND table_schema = 'io_thecodeforge';
Check for missing REFERENCES via SHOW CREATE TABLE.
Fix now
ALTER TABLE ADD FOREIGN KEY constraint; optionally add ON DELETE CASCADE.
ER Diagram Symbols vs SQL Equivalents
Concept
ER Diagram Symbol
SQL Equivalent
Real Example
Entity
Rectangle
Table (CREATE TABLE)
STUDENT, COURSE, PROFESSOR
Key Attribute
Oval with underline
PRIMARY KEY column
student_id, course_id
Simple Attribute
Oval
Regular column
first_name, email
Composite Attribute
Oval with sub-ovals
Multiple columns
full_name → first_name + last_name
Multi-valued Attribute
Double oval
Separate table with FK
phone_numbers → StudentPhone table
Derived Attribute
Dashed oval
Calculated column / formula
age derived from date_of_birth
Relationship (1:1)
Diamond + 1 and 1 labels
UNIQUE foreign key
PERSON has one PASSPORT
Relationship (1:N)
Diamond + 1 and N labels
Foreign key on 'N' side
PROFESSOR teaches many COURSEs
Relationship (M:N)
Diamond + M and N labels
Junction/bridge table
STUDENT enrolls in COURSE
Weak Entity
Double rectangle
Composite primary key
ORDER_ITEM depends on ORDER
Total Participation
Double line to relationship
NOT NULL foreign key
Every order MUST have a customer
Partial Participation
Single line to relationship
Nullable foreign key
A professor MAY have a department
Specialisation (ISA)
Triangle with dividing lines
Shared primary key across tables
Person / Employee / Student
Key takeaways
1
An ER diagram is your database blueprint
draw it before writing a single line of SQL, or risk rebuilding everything later when data relationships don't match reality.
2
Cardinality (1:1, 1:N, M:N) dictates the table structure
specifically, M:N relationships always need a separate junction table; there is no shortcut.
3
A weak entity's full identity = owner's primary key + its own partial key; in SQL this always becomes a composite PRIMARY KEY, never a standalone one.
4
Multi-valued attributes and M:N relationships both become their own tables in SQL
any time one cell would need to hold a list of values, a new table is the answer.
5
Derived attributes should never be stored
always compute them from base attributes at query time. Storing age instead of birth date is a classic trap.
6
Specialisation (ISA hierarchy) maps to separate tables with a shared primary key
never merge all subclasses into one wide table with nullable columns.
Common mistakes to avoid
4 patterns
×
Treating a Many-to-Many relationship as directly storable
Symptom
You try to store multiple product IDs in a single order row using a JSON array or comma-separated list. Queries become impossible, data integrity breaks, and reporting is unreliable.
Fix
Always create a junction table (like OrderItem) that holds foreign keys from both sides and allows relationship attributes. Each row represents one pairing.
×
Confusing an entity with an attribute
Symptom
You model 'Department' as just a text column on Employee. Then you can't store department phone, location, or manager without duplicating data.
Fix
If a concept has its own properties or connects to multiple entities, promote it to a full entity with its own table. Apply the 'has properties?' test.
×
Forgetting that a weak entity's identifier is always composite
Symptom
You give ORDER_ITEM its own auto-incremented ID and never link the item number to its parent order. Item #3 now exists in a vacuum.
Fix
The primary key of a weak entity's table must be a composite of (owner_pk, partial_key). Use ON DELETE CASCADE to automatically clean up when the owner is deleted.
×
Using a single table for all subtypes in a specialisation hierarchy
Symptom
You have a Person table with many nullable columns for employee-specific fields (salary, hire_date) and student-specific fields (major, enrollment_year). Table becomes wide, constraints are lost, and subsets are hard to query.
Fix
Create a superclass table with shared columns and separate subclass tables with the same primary key. Use shared primary key and FK to enforce the ISA relationship.
INTERVIEW PREP · PRACTICE MODE
Interview Questions on This Topic
Q01SENIOR
What is the difference between a strong entity and a weak entity? Can yo...
Q02SENIOR
How do you convert a Many-to-Many relationship from an ER diagram into a...
Q03JUNIOR
If 'Age' is a derived attribute in an ER diagram, should you store it as...
Q04SENIOR
Explain the difference between total and partial participation with a re...
Q05SENIOR
How would you represent a ternary relationship (involving three entities...
Q01 of 05SENIOR
What is the difference between a strong entity and a weak entity? Can you give a real-world example of each?
ANSWER
A strong entity can be uniquely identified by its own attributes — it exists independently. Example: ORDER (order_id is sufficient). A weak entity depends on another entity for identification — its full key includes the owner's primary key. Example: ORDER_ITEM (item_number + order_id). The weak entity is drawn with a double rectangle and the identifying relationship with a double diamond. In SQL, weak entities have a composite primary key and a foreign key with ON DELETE CASCADE.
Q02 of 05SENIOR
How do you convert a Many-to-Many relationship from an ER diagram into a relational database schema? Walk me through the steps.
ANSWER
First, identify the two entities involved. Create a new 'junction' table (also called associative entity). This table will contain two foreign key columns, each referencing the primary key of one of the original entities. The primary key of the junction table is typically a composite of those two foreign keys, unless the relationship itself has attributes, in which case you may introduce a surrogate key. Add any relationship-specific attributes (e.g., enrollment_date) as columns. Finally, define foreign key constraints and a UNIQUE constraint if a pairing should be unique. Example: Student-Course requires Enrollment table with student_id, course_id, enrollment_date, grade.
Q03 of 05JUNIOR
If 'Age' is a derived attribute in an ER diagram, should you store it as a column in your database table? What are the trade-offs?
ANSWER
No, you should not store derived attributes. Store the base attribute (date_of_birth) and calculate Age at query time. The trade-offs: storing derived values can speed up reads but introduces data inconsistency — the age becomes stale as time passes unless you have a batch job to update it daily. Calculating on the fly is cheap (microseconds) and guarantees accuracy. The only exception is if you need to snapshot the derived value at a point in time (e.g., age at enrollment), in which case store it as a non-derived attribute with a clear name like 'age_at_enrollment'.
Q04 of 05SENIOR
Explain the difference between total and partial participation with a real example.
ANSWER
Total participation means every instance of an entity MUST be involved in the relationship. In ER diagrams, it's shown with a double line. Example: Every ORDER must have a CUSTOMER — total participation from ORDER side. Partial participation means some instances may not be involved. Shown with a single line. Example: Not every PROFESSOR advises a student — some professors have no advisees. In SQL, total participation translates to a NOT NULL foreign key, while partial participation translates to a nullable foreign key. Getting this wrong can cause constraint violations or allow incomplete data.
Q05 of 05SENIOR
How would you represent a ternary relationship (involving three entities) in an ER diagram and then in SQL?
ANSWER
In an ER diagram, a ternary relationship is drawn as a diamond connected to three entity rectangles, with cardinality ratios marked on each edge (usually 1:1:1 or 1:1:N, etc.). In SQL, a ternary relationship is implemented as a junction table with three foreign keys — one referencing each entity's primary key. The primary key of the junction table is typically a composite of all three foreign keys (or a subset if some combinations are unique). For example, a SUPPLIER ships PART to WAREHOUSE: you would create a Shipment table with supplier_id, part_id, warehouse_id as a composite PK, plus attributes like quantity and ship_date.
01
What is the difference between a strong entity and a weak entity? Can you give a real-world example of each?
SENIOR
02
How do you convert a Many-to-Many relationship from an ER diagram into a relational database schema? Walk me through the steps.
SENIOR
03
If 'Age' is a derived attribute in an ER diagram, should you store it as a column in your database table? What are the trade-offs?
JUNIOR
04
Explain the difference between total and partial participation with a real example.
SENIOR
05
How would you represent a ternary relationship (involving three entities) in an ER diagram and then in SQL?
SENIOR
FAQ · 5 QUESTIONS
Frequently Asked Questions
01
What is the difference between an ER model and an ER diagram?
The ER Model is the theoretical framework — the set of rules and concepts (entities, attributes, relationships, cardinality) for describing data. An ER diagram is the actual visual drawing you create by applying those rules to a specific system. The model is the language; the diagram is the sentence you write in that language.
Was this helpful?
02
Why do we need an ER diagram if we're just going to write SQL tables anyway?
Because fixing a bad database design after data is already in it is enormously expensive and painful. An ER diagram lets you spot structural problems — missing relationships, wrongly placed attributes, forgotten entities — at the planning stage when changes cost nothing. It's the same reason architects draw blueprints instead of just starting to pour concrete.
Was this helpful?
03
What is the difference between cardinality and participation constraints in an ER model?
Cardinality answers 'how many?' — specifically, how many instances of entity A can relate to how many instances of entity B (1:1, 1:N, M:N). Participation answers 'is it mandatory?' — total participation means every single instance MUST be in the relationship (e.g., every order item must belong to an order), while partial participation means it's optional (e.g., a professor may or may not advise a student project). Both appear on the same relationship line but describe different things.
Was this helpful?
04
Can an ER diagram have more than one relationship between two entities?
Yes, absolutely. For example, a Person can be both an Employee and a Manager. The same two entities can have multiple diamonds between them to represent different associations. In a company database, Employee and Department may have a 'works_in' relationship (1:N) and a 'manages' relationship (1:1). Each relationship is distinct and may have its own attributes.
Was this helpful?
05
What happens if I skip the ER diagram and go straight to table design?
You'll likely miss entities, misplace attributes, misunderstand cardinality, and create a schema full of redundancy and anomalies. The first time you try to add a feature like 'track which student borrowed which book copy on which date', you'll need a painful migration. ER diagrams are cheap insurance against expensive rework.