ER Model in DBMS Explained — Entities, Attributes, and Relationships
Every app you've ever 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.
-- ============================================================ -- Translating ER Entities and Attributes into a real SQL table -- This is what your ER diagram eventually becomes in a database -- ============================================================ -- 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) CREATE TABLE Student ( student_id INT PRIMARY KEY, -- Key attribute: uniquely identifies each student first_name VARCHAR(50) NOT NULL, -- Part of composite attribute 'FullName' last_name VARCHAR(50) NOT NULL, -- Part of composite attribute 'FullName' date_of_birth DATE NOT NULL, -- We store this; Age is DERIVED from it email VARCHAR(100) UNIQUE NOT NULL -- Simple attribute ); -- Multi-valued attribute 'PhoneNumbers' becomes its own table. -- A student can have 0, 1, or many phone numbers. CREATE TABLE StudentPhone ( phone_id INT PRIMARY KEY, student_id INT NOT NULL, -- Links back to the Student table phone_number VARCHAR(15) NOT NULL, FOREIGN KEY (student_id) REFERENCES Student(student_id) ); -- ENTITY: Course CREATE TABLE Course ( course_id INT PRIMARY KEY, -- Key attribute for Course entity course_name VARCHAR(100) NOT NULL, credits INT NOT NULL ); -- Insert sample data so we can see real instances INSERT INTO Student VALUES (101, 'Alice', 'Morgan', '2001-04-15', 'alice@uni.edu'); INSERT INTO Student VALUES (102, 'Bob', 'Chen', '2000-09-22', 'bob@uni.edu'); INSERT INTO StudentPhone VALUES (1, 101, '555-0101'); -- Alice has one phone INSERT INTO StudentPhone VALUES (2, 101, '555-0202'); -- Alice has a second phone INSERT INTO StudentPhone VALUES (3, 102, '555-0303'); -- Bob has one phone INSERT INTO Course VALUES (1, 'Database Systems', 3); INSERT INTO Course VALUES (2, 'Data Structures', 4); -- Query to see Alice's full record including derived age SELECT student_id, first_name || ' ' || last_name AS full_name, -- Composite attribute reconstructed EXTRACT(YEAR FROM AGE(date_of_birth)) AS age, -- Derived attribute calculated on the fly email FROM Student WHERE student_id = 101;
------------+--------------+-----+----------------
101 | Alice Morgan | 23 | alice@uni.edu
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.
-- ============================================================ -- Translating ER Relationships and Cardinality into SQL -- ============================================================ -- Relationship: PROFESSOR teaches COURSE (One-to-Many: 1 professor → many courses) -- We implement 1:N by placing the foreign key on the 'many' side (Course table) CREATE TABLE Professor ( professor_id INT PRIMARY KEY, full_name VARCHAR(100) NOT NULL, department VARCHAR(50) NOT NULL ); -- Each Course row holds a professor_id — the 'one' side of the relationship ALTER TABLE Course ADD COLUMN professor_id INT, ADD CONSTRAINT fk_course_professor FOREIGN KEY (professor_id) REFERENCES Professor(professor_id); -- Relationship: STUDENT enrolls in COURSE (Many-to-Many) -- M:N relationships ALWAYS become their own 'junction' table in SQL -- The junction table holds the primary keys of BOTH entities -- It can also hold relationship-specific attributes (like enrollment_date) CREATE TABLE Enrollment ( enrollment_id INT PRIMARY KEY, student_id INT NOT NULL, course_id INT NOT NULL, enrollment_date DATE NOT NULL, -- Attribute of the RELATIONSHIP itself grade CHAR(2), -- Also a relationship attribute — Alice's grade in THIS course FOREIGN KEY (student_id) REFERENCES Student(student_id), FOREIGN KEY (course_id) REFERENCES Course(course_id), UNIQUE (student_id, course_id) -- Prevent duplicate enrollments for the same student+course ); -- Relationship: PERSON has PASSPORT (One-to-One: 1:1) -- We implement 1:1 with a UNIQUE foreign key CREATE TABLE Person ( person_id INT PRIMARY KEY, full_name VARCHAR(100) NOT NULL ); CREATE TABLE Passport ( passport_id INT PRIMARY KEY, passport_number VARCHAR(20) UNIQUE NOT NULL, person_id INT UNIQUE NOT NULL, -- UNIQUE enforces the 1:1 — one passport per person expiry_date DATE NOT NULL, FOREIGN KEY (person_id) REFERENCES Person(person_id) ); -- ---- Sample Data ---- INSERT INTO Professor VALUES (1, 'Dr. Sarah Hill', 'Computer Science'); INSERT INTO Professor VALUES (2, 'Dr. James Okafor','Mathematics'); UPDATE Course SET professor_id = 1 WHERE course_id = 1; -- Dr. Hill teaches Database Systems UPDATE Course SET professor_id = 1 WHERE course_id = 2; -- Dr. Hill also teaches Data Structures INSERT INTO Enrollment VALUES (1, 101, 1, '2024-01-10', 'A'); -- Alice enrolled in Database Systems INSERT INTO Enrollment VALUES (2, 101, 2, '2024-01-10', 'B+'); -- Alice also in Data Structures INSERT INTO Enrollment VALUES (3, 102, 1, '2024-01-11', NULL); -- Bob in Database Systems, no grade yet -- Query: Find all courses Alice is enrolled in, with her grades SELECT s.first_name || ' ' || s.last_name AS student_name, c.course_name, e.enrollment_date, COALESCE(e.grade, 'Not graded') AS grade FROM Enrollment e JOIN Student s ON e.student_id = s.student_id JOIN Course c ON e.course_id = c.course_id WHERE e.student_id = 101 ORDER BY c.course_name;
---------------+-------------------+-----------------+------------
Alice Morgan | Data Structures | 2024-01-10 | B+
Alice Morgan | Database Systems | 2024-01-10 | A
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: ORDER_ITEM depends on ORDER for its identity -- Specialisation: EMPLOYEE and STUDENT are subtypes of PERSON -- ============================================================ -- Strong entity: ORDER CREATE TABLE CustomerOrder ( order_id INT PRIMARY KEY, -- Strong entity has its own full key order_date DATE NOT NULL, customer_name VARCHAR(100) NOT NULL ); -- Weak entity: ORDER_ITEM -- 'item_number' is the PARTIAL KEY — only unique within a specific order -- The FULL identity is (order_id + item_number) combined CREATE TABLE OrderItem ( order_id INT NOT NULL, -- Foreign key to the owner (strong) entity item_number INT NOT NULL, -- Partial key — dashed underline in ER diagram product_name VARCHAR(100) NOT NULL, quantity INT NOT NULL, unit_price DECIMAL(8,2) NOT NULL, -- Combined primary key: order_id + item_number together form the full identifier PRIMARY KEY (order_id, item_number), FOREIGN KEY (order_id) REFERENCES CustomerOrder(order_id) ON DELETE CASCADE -- If the order is deleted, all its items are deleted too ); -- ---- Specialisation / Generalisation ---- -- PERSON is the generalised (parent) entity with shared attributes CREATE TABLE Person ( person_id INT PRIMARY KEY, full_name VARCHAR(100) NOT NULL, date_of_birth DATE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL ); -- EMPLOYEE is a specialised subtype — it has all Person attributes PLUS its own CREATE TABLE Employee ( person_id INT PRIMARY KEY, -- Shares the same ID as Person employee_code VARCHAR(20) UNIQUE NOT NULL, hire_date DATE NOT NULL, salary DECIMAL(10,2) NOT NULL, FOREIGN KEY (person_id) REFERENCES Person(person_id) -- ISA relationship ); -- STUDENT is another specialised subtype — different extra attributes CREATE TABLE Student_Person ( person_id INT PRIMARY KEY, -- Same ID as Person student_id VARCHAR(20) UNIQUE NOT NULL, enrollment_year INT NOT NULL, major VARCHAR(50), FOREIGN KEY (person_id) REFERENCES Person(person_id) -- ISA relationship ); -- ---- Sample Data ---- INSERT INTO CustomerOrder VALUES (500, '2024-03-01', 'Greenleaf Supplies'); INSERT INTO CustomerOrder VALUES (501, '2024-03-02', 'BlueStar Corp'); -- Order 500 has 3 items; item_number restarts at 1 for each order INSERT INTO OrderItem VALUES (500, 1, 'Printer Paper A4', 10, 5.99); INSERT INTO OrderItem VALUES (500, 2, 'Black Ink Cartridge', 3, 18.50); INSERT INTO OrderItem VALUES (500, 3, 'Stapler', 1, 12.00); -- Order 501 also has an item_number = 1 — NOT a conflict because order_id differs INSERT INTO OrderItem VALUES (501, 1, 'Whiteboard Markers', 5, 3.25); -- Specialisation: one person who is an employee INSERT INTO Person VALUES (1, 'Carol White', '1985-07-20', 'carol@company.com'); INSERT INTO Employee VALUES (1, 'EMP-00421', '2015-03-01', 72000.00); -- Retrieve a full order with its line items and running total SELECT 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 CustomerOrder o JOIN OrderItem i ON o.order_id = i.order_id WHERE o.order_id = 500 ORDER BY i.item_number;
----------+--------------------+-------------+------------------------+----------+------------+-----------
500 | Greenleaf Supplies | 1 | Printer Paper A4 | 10 | 5.99 | 59.90
500 | Greenleaf Supplies | 2 | Black Ink Cartridge | 3 | 18.50 | 55.50
500 | Greenleaf Supplies | 3 | Stapler | 1 | 12.00 | 12.00
| 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 |
🎯 Key Takeaways
- 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.
- 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.
- 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.
- 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.
⚠ Common Mistakes to Avoid
- ✕Mistake 1: Treating a Many-to-Many relationship as if it can be stored directly — Symptom: you try to store multiple course IDs in a single student row, creating something like 'course_ids = 1,2,3' in one column, which breaks every query — Fix: always create a junction table (like Enrollment) with foreign keys to both sides, and let each row represent one specific pairing.
- ✕Mistake 2: Confusing an entity with an attribute — Symptom: you model 'Department' as just an attribute (a text column) on Employee instead of its own entity, which means you can't store a department's phone number, location, or manager without duplicating data everywhere — Fix: if a concept has its own properties or connects to multiple other entities, promote it to a full entity with its own table.
- ✕Mistake 3: 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, so 'item 3' now exists in a vacuum with no guaranteed connection to the right order — Fix: make the primary key of a weak entity's table a composite of (owner_pk, partial_key), and use ON DELETE CASCADE so orphaned items can't exist.
Interview Questions on This Topic
- QWhat is the difference between a strong entity and a weak entity? Can you give a real-world example of each?
- QHow do you convert a Many-to-Many relationship from an ER diagram into a relational database schema? Walk me through the steps.
- QIf '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?
Frequently Asked Questions
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.
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.
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.
Written and reviewed by senior developers with real-world experience across enterprise, startup and open-source projects. Every article on TheCodeForge is written to be clear, accurate and genuinely useful — not just SEO filler.