🏛 Data Modeling

2. Logical Data Model

Add attributes, primary keys, and foreign keys — still database-agnostic, but fully detailed.

What is a Logical Data Model?

The Logical Data Model (LDM) is your CDM with all the details added:

The LDM is still database-agnostic. You haven't picked Oracle vs MySQL vs Postgres yet. The audience is data architects and designers.

Starting from the CDM

If you saved your CDM file, open it. We'll add attributes and resolve the many-to-many relationship.

1

Switch to Logical display mode

Make sure you're in Logical view:

The entities now show separator lines for attributes (currently empty). They look like:

┌─────────────────────┐ │ Customer │ ├─────────────────────┤ │ │ │ │ └─────────────────────┘
2

Add attributes to Customer

Double-click the Customer entity to open the Property Editor. Click the Attributes tab.

Click New to add each attribute:

  • Customer ID — check the Primary Key checkbox; datatype = Number
  • First Name — datatype = String
  • Last Name — datatype = String
  • Email — datatype = String; check Unique alternate key
  • Phone — datatype = String; optional (don't check Not Null)
  • Created Date — datatype = Datetime

Click OK. The Customer entity now shows all six attributes, with "Customer ID" above the divider line (because it's the PK) and the others below.

2.5

Why the divider line matters

ERWIN entities have a horizontal line splitting them into two zones:

Above the line

Primary key attributes. These uniquely identify each row.

Below the line

Non-key attributes — all the descriptive data.

Foreign keys appear below the line marked with (FK) after the attribute name. Identifying-relationship FKs go above the line (because they're part of the child's PK).

3

Add attributes to all other entities

Repeat for each entity. Suggested attributes:

Address

  • Address ID — PK, Number
  • Street Line 1 — String
  • Street Line 2 — String, optional
  • City — String
  • State — String
  • Postal Code — String
  • Country — String
  • Address Type — String ("Shipping", "Billing")

Category

  • Category ID — PK, Number
  • Category Name — String, Unique
  • Description — String, optional

Product

  • Product ID — PK, Number
  • Product Name — String
  • SKU — String, Unique
  • Unit Price — Money
  • Stock Quantity — Number
  • Active — Boolean

Order

  • Order ID — PK, Number
  • Order Date — Datetime
  • Order Status — String ("Pending", "Shipped", "Delivered", "Cancelled")
  • Total Amount — Money
4

Foreign keys propagate automatically

Look at the Order entity now. It should automatically show:

  • Customer ID (FK) — propagated from the Customer → Order relationship
  • Address ID (FK) — propagated from the Order → Address relationship (shipping address)

You didn't have to add these manually. This is the magic of ERWIN: when you draw a relationship, the parent's PK automatically appears in the child as an FK. Move the relationship, the FK moves. Rename the PK, the FK renames everywhere.

Migration ERWIN calls this automatic FK propagation "migration". It's the single biggest reason people use ERWIN over hand-drawn diagrams — you don't have to keep FKs in sync manually.
5

Resolve the many-to-many Order ↔ Product

Right-click the M:N relationship line between Order and Product. Choose Convert to Associative Entity (older versions: "Resolve M:N").

ERWIN inserts a new entity between Order and Product, with two 1:N relationships pointing in. By default it's called "Order_Product" — rename it to Order Line (or "Order Item" / "Line Item" — whatever your business calls it).

Add attributes to Order Line:

  • Order Line ID — PK, Number (this is the standalone PK)
  • Quantity — Number
  • Unit Price At Time Of Order — Money
  • Line Total — Money
  • Order ID (FK) — already there from migration
  • Product ID (FK) — already there from migration
Why a separate Order Line ID? You could make (Order ID, Product ID) a composite PK. But adding a surrogate key (Order Line ID) is cleaner because: (1) joins are faster on a single integer, (2) the same product can appear on the same order twice (different size, gift wrap variant) without breaking the PK.
6

Use domains for consistent data types

You'll notice you've been typing "String" and "Money" repeatedly. ERWIN's Domains let you define these once and reuse them.

Common domains to create:

  • Money — Decimal, precision 18, scale 4
  • ShortText — String, length 50
  • LongText — String, length 500
  • ID — Big Integer, identity/auto-increment
  • AuditTimestamp — Datetime, default current_timestamp

Now when adding new attributes, you can pick the domain instead of typing a type. Change the domain definition once and every attribute using it updates automatically.

7

Set Not Null and check constraints

Reopen Property Editor for each entity. For each attribute, set:

  • Not Null — for fields that must always have a value (PKs, names, emails)
  • Check constraint — for fields with valid values (e.g., Order Status IN ('Pending','Shipped','Delivered','Cancelled'))
  • Default value — sensible defaults (Active = true, Created Date = current_timestamp)

These constraints will translate to SQL CHECK constraints in the physical model.

8

Validate the model

ERWIN can check your model for common problems:

It'll flag:

  • Entities without primary keys
  • Relationships without verb phrases
  • Attributes without data types
  • Missing definitions on entities
  • Naming convention violations (we'll set up rules in the Physical lesson)

Fix anything flagged, save your work as ecommerce_logical.erwin, and you've completed a proper logical data model.

What our LDM looks like now

┌─────────────────────────┐ ┌──────────────────────┐ │ Customer │ │ Address │ ├─────────────────────────┤ ├──────────────────────┤ │ PK Customer ID │◄────────│ FK Customer ID │ │ First Name │ │ PK Address ID │ │ Last Name │ │ Street Line 1 │ │ Email │ │ City │ │ Phone │ │ State │ │ Created Date │ │ Address Type │ └─────────────────────────┘ └──────────────────────┘ │ │ (places) ▼ ┌─────────────────────────┐ ┌──────────────────────┐ │ Order │ │ Order Line │ ├─────────────────────────┤ ├──────────────────────┤ │ PK Order ID │◄────────│ FK Order ID │ │ FK Customer ID │ │ PK Order Line ID │ │ FK Shipping Address ID │ │ FK Product ID │ │ Order Date │ │ Quantity │ │ Order Status │ │ Unit Price │ │ Total Amount │ │ Line Total │ └─────────────────────────┘ └──────────────────────┘ │ │ (refers to) ▼ ┌──────────────────────┐ │ Product │ ├──────────────────────┤ │ PK Product ID │ │ FK Category ID │ │ Product Name │ │ SKU │ │ Unit Price │ └──────────────────────┘

Normalization check

Walk through 1NF, 2NF, 3NF:

If you find a 3NF violation (e.g., Customer.City and Customer.State, where State depends on City), break it into a separate lookup entity.

You've completed the Logical Model At this point your model is fully designed but database-agnostic. You could implement this on Oracle, SQL Server, PostgreSQL, or MySQL — the logical structure is the same. Next lesson: pick a target DB and turn this into a Physical Data Model with real data types and indexes.