The Story That Explains the Mapping
Converting an ER diagram into a relational schema is exactly this rewrite. The ER diagram is the conceptual sketch; the relational schema is the buildable worksheet of tables, columns, primary keys, and foreign keys that an RDBMS like MySQL or Oracle can actually create.
The ER model is a conceptual design; the relational model is a logical design that maps almost one-to-one onto real tables. We cannot carry every ER constraint across perfectly, but a faithful, implementable schema can always be produced by following a small set of mechanical rules.
Entities become tables, attributes become columns, keys become primary keys, and relationships become foreign keys — or, when both sides are "many", a brand-new table of their own.
The Big Picture — What Maps to What
Before the step-by-step rules, hold this translation table in your head. Every ER construct on the left has a fixed home on the right.
The conversion is the bridge between conceptual design (what we mean) and logical design (what we build).
| ER Construct | Becomes in the Relational Schema |
|---|---|
| Strong entity | A table (relation) |
| Weak entity | A table whose key includes the owner's key |
| Simple attribute | A column |
| Composite attribute | One column per leaf component |
| Multivalued attribute | A separate table |
| Derived attribute | Usually not stored |
| Key attribute | Primary key |
| 1:1 / 1:N relationship | A foreign key (no new table) |
| M:N relationship | A new junction table |
The Seven-Step Mapping Algorithm
Almost every textbook follows the same seven steps, in this order. Run them top to bottom and any ER diagram becomes a complete schema.
Steps 1–2 create all the tables first, so that when steps 3–7 add foreign keys, every table they need to point at already exists. Do entities before relationships, always.
Step 1 — Strong Entities Become Tables
For each strong entity, create a table with the same name. Every simple, single-valued attribute becomes a column, and the entity's key attribute becomes the primary key (shown underlined in the diagram, marked PK in the schema).
The underlined key attribute Roll_No becomes the primary key of the table.
-- Step 1 : strong entity to table
STUDENT ( Roll_No PK, Name, Age )
Handling Composite, Derived & Multivalued Attributes
Three attribute types need special care, because relational tables only allow atomic, single-valued columns. The diagram below is the summary; the three sub-sections after it explain each case in detail, with the exact tables that get created.
Flatten composites into their leaves, drop derived attributes, and lift multivalued attributes into a child table keyed by the owner.
A. Composite Attributes — One Column per Leaf
A composite attribute is one that can be split into smaller sub-parts. For example, Name splits into First_Name and Last_Name, and Address splits into House_No, City, and PIN. A relational column must be atomic, so we cannot keep the composite "root" as a single column.
Create one column for each leaf component of the composite attribute and discard the root name. So Name never becomes a column — First_Name and Last_Name do.
Here is how each composite attribute of EMPLOYEE flattens into columns:
| Composite attribute (root) | Leaf components | Columns created |
|---|---|---|
| Name (ignored) | First, Last | First_Name, Last_Name |
| Address (ignored) | House_No, City, PIN | House_No, City, PIN |
The resulting EMPLOYEE table — the composite roots have vanished, only their leaves remain as real columns:
| Emp_ID (PK) | First_Name | Last_Name | House_No | City | PIN |
|---|---|---|---|---|---|
| E1 | Raj | Verma | 12 | Delhi | 110001 |
| E2 | Sara | Khan | 7B | Pune | 411001 |
-- Composite Name and Address are flattened into leaf columns
EMPLOYEE ( Emp_ID PK, First_Name, Last_Name, House_No, City, PIN )
B. Derived Attributes — Don't Store It, Compute It
A derived attribute is one whose value can be calculated from other data that is already stored. Age can be derived from Date_of_Birth; an order's Total can be derived from Quantity and Unit_Price. Storing a derived value is a mistake: it wastes space and quickly goes stale (your stored Age would be wrong on the next birthday).
Do not create a column for the derived attribute. Store only the base data (e.g. DOB), then compute the value at query time, in a database view, or in the application — so it is always fresh.
What you actually store — notice there is no Age column:
| Roll_No (PK) | Name | DOB (stored) |
|---|---|---|
| 101 | Raj | 2004-05-10 |
| 102 | Sara | 2003-11-22 |
What the user sees when they ask for it — Age is calculated fresh (here, as of 2026):
| Roll_No | Name | Age (computed, not stored) |
|---|---|---|
| 101 | Raj | 22 |
| 102 | Sara | 22 |
How to calculate it — the derived value is produced by a formula at read time, for example with a query or a view (no extra storage):
-- Age is NEVER stored; it is computed from DOB whenever needed
SELECT Roll_No, Name,
FLOOR( DATEDIFF(CURRENT_DATE, DOB) / 365.25 ) AS Age
FROM STUDENT;
-- Or expose it permanently as a VIEW (still nothing extra is stored)
CREATE VIEW STUDENT_AGE AS
SELECT Roll_No, Name,
FLOOR( DATEDIFF(CURRENT_DATE, DOB) / 365.25 ) AS Age
FROM STUDENT;
The same principle covers every derived attribute — store the inputs, write the formula:
| Derived attribute | Stored base data | Calculation (formula) |
|---|---|---|
| Age | DOB | today − DOB, in whole years |
| Total_Price | Quantity, Unit_Price | Quantity × Unit_Price |
| Experience | Join_Date | today − Join_Date, in years |
| Line_Total | Qty, Rate, Discount | (Qty × Rate) − Discount |
C. Multivalued Attributes — Create a Separate Table
A multivalued attribute can hold many values for a single entity — an employee may have several phone numbers, a person may have many skills. A single column can hold only one value, so a multivalued attribute cannot live inside the entity's own table.
Cramming many values into one cell — Phone_No = "99887766, 99112233" — breaks first normal form (1NF) and makes searching, updating, and counting phone numbers painful.
Create a separate table containing the owner's primary key (as a foreign key) plus the multivalued attribute. Its primary key is the combination of both, so each value gets its own row.
The main EMPLOYEE table keeps only single-valued data:
| Emp_ID (PK) | Name |
|---|---|
| E1 | Raj |
| E2 | Sara |
The new EMP_PHONE table stores one row per phone number — so E1's two phones become two rows:
| Emp_ID (FK, part of PK) | Phone_No (part of PK) |
|---|---|
| E1 | 99887766 |
| E1 | 99112233 |
| E2 | 90011223 |
-- Multivalued Phone_No is lifted out into its own table
EMPLOYEE ( Emp_ID PK, Name )
EMP_PHONE ( Emp_ID FK, Phone_No ) -- PK = (Emp_ID, Phone_No)
Composite → split into one column per leaf. Derived → store nothing, compute from base data with a formula. Multivalued → move into its own child table, one value per row.
Step 3 — Mapping 1:1 Relationships
A one-to-one relationship needs no new table. Put the primary key of one entity into the other as a foreign key. Prefer the side with total participation — it minimises NULLs, because that side always has a partner.
Passport has total participation (a passport must have an owner), so it takes the foreign key.
-- Step 3 : 1:1 mapped with a foreign key (+ UNIQUE keeps it 1:1)
PERSON ( Person_Id PK, Name )
PASSPORT ( Pass_No PK, Issue_Dt, Person_Id FK UNIQUE )
Step 4 — Mapping 1:N Relationships
This is the most common case. Place the primary key of the "one" side into the "many" side as a foreign key. No new table is needed — the foreign key is the relationship.
Customer C1 appears against both L1 and L2 — perfectly legal, because the foreign key sits on the "many" side.
-- Step 4 : 1:N mapped with a foreign key on the many side
CUSTOMER ( Cust_No PK, Name, City )
LOAN ( Loan_No PK, Amount, Cust_No FK )
If you tried to store loan references inside CUSTOMER, a single customer row would need to hold many loan numbers in one cell — which relational tables forbid. The foreign key must always live on the many side.
Step 5 — Mapping M:N Relationships
When both sides are "many", a foreign key cannot capture it. Create a brand-new junction table (also called a relationship or cross-reference table) holding the primary keys of both entities plus any descriptive attributes of the relationship.
The junction table borrows both primary keys as foreign keys; together they form its composite primary key.
-- Step 5 : M:N mapped to a junction table
STUDENT ( Roll_No PK, Name )
COURSE ( Course_ID PK, Title )
ENROLLS ( Roll_No FK, Course_ID FK, Grade ) -- PK = (Roll_No, Course_ID)
Step 2 — Mapping Weak Entities
A weak entity becomes a table that includes the owner's primary key as a foreign key. Its primary key is the combination of that foreign key and the weak entity's partial key (discriminator).
Payment_No "1" repeats across loans, but (L1, 1) and (L2, 1) are distinct — uniqueness restored by the composite key.
-- Step 2 : weak entity borrows the owner's key
LOAN ( Loan_No PK, Amount )
PAYMENT ( Loan_No FK, Payment_No, Pay_Date ) -- PK = (Loan_No, Payment_No)
Step 7 — Mapping n-ary Relationships
A relationship connecting three or more entities (degree > 2) always becomes its own table. Include the primary key of every participating entity as a foreign key, plus any descriptive attributes. The combination of those foreign keys is normally the primary key.
| Ternary relationship | Resulting table |
|---|---|
| DOCTOR – PATIENT – DRUG (via PRESCRIBES) | PRESCRIBES(Doctor_ID FK, Patient_ID FK, Drug_ID FK, Dose) |
| SUPPLIER – PROJECT – PART (via SUPPLIES) | SUPPLIES(Sup_ID FK, Proj_ID FK, Part_ID FK, Qty) |
An n-ary relationship is just a many-to-many across more than two entities. The recipe is identical — a separate table holding everyone's key — only with more foreign-key columns.
A Complete Worked Example
Let us convert a small University ER diagram end to end. It contains two strong entities (DEPARTMENT, STUDENT, COURSE), a 1:N relationship, an M:N relationship with a descriptive attribute, and a multivalued attribute.
Strong entities → tables; 1:N → FK in STUDENT; M:N → ENROLLS; multivalued phone → STUDENT_PHONE.
-- Final relational schema
DEPARTMENT ( Dept_ID PK, Dname )
STUDENT ( Roll_No PK, Name, Dept_ID FK )
COURSE ( Course_ID PK, Title )
ENROLLS ( Roll_No FK, Course_ID FK, Grade ) -- PK = (Roll_No, Course_ID)
STUDENT_PHONE ( Roll_No FK, Phone_No ) -- PK = (Roll_No, Phone_No)
Common Mistakes to Avoid
Only M:N and n-ary relationships need their own table. For 1:1 and 1:N, a single foreign key is enough — an extra table just adds needless joins.
Storing "99887766, 99112233" in a single Phone column breaks first normal form. Every multivalued attribute earns its own child table keyed by the owner.
A weak entity's partial key is not unique on its own. Its table's primary key must combine the owner's primary key with the partial key, or rows will collide.
Quick Reference Cheat Sheet
| ER Construct | Mapping Rule | New Table? |
|---|---|---|
| Strong entity | Table; key attribute → PK | Yes |
| Weak entity | Table; PK = owner PK + partial key | Yes |
| Composite attribute | One column per leaf component | No |
| Derived attribute | Omitted (computed on demand) | No |
| Multivalued attribute | Child table keyed by owner | Yes |
| 1:1 relationship | FK on either side (prefer total) | No |
| 1:N relationship | FK on the "many" side | No |
| M:N relationship | Junction table with both PKs | Yes |
| n-ary relationship | Table with all participants' PKs | Yes |