Crow's foot notation: a visual cheat sheet
Every ER diagram ends up saying the same three things: which tables exist, which columns link them, and how many rows one row can relate to on the other side. Crow's foot notation is just the shorthand for that last part - four little symbols that turn "a user has orders, plural, but maybe none yet" into a mark on a line.
The four endings
Every line end is one of these - nothing more to memorize:
| Ending | Name | Read as | In SQL |
|---|---|---|---|
two ticks ‖ | Exactly one | must have one, only one | FK NOT NULL + UNIQUE |
ring + tick o‖ | Zero or one | may have one, or none | nullable FK + UNIQUE |
tick + foot ‖< | One or many | must have at least one | FK NOT NULL (child rows required) |
ring + foot o< | Zero or many | may have any number | plain FK, nullable or not |
Two building blocks make all four: the foot (three prongs) means many, and the ring means optional. No ring means the relationship is mandatory.
How to read a line out loud
Stand at the one side, walk toward the far table, and narrate what you pass:
users ||--o{ orders
"Users" - ticks mean exactly one - "each user" - ring plus foot means
zero or many - "has zero or more orders." One sentence, and it doubles
as the foreign-key rule: orders.user_id points at users.id, and it's
nullable precisely because the ring says zero is allowed.
A full example
Reading all three lines out loud:
users ‖—o{ orders- each order belongs to exactly one user; a user can have any number of orders (orders.user_id)orders ‖—|{ order_items- an order needs at least one line item; an item belongs to exactly one order (order_items.order_id,NOT NULL)products ‖—o{ order_items- a product can appear on many items, or none yet (order_items.product_id)
That middle line is the one people get wrong - an empty order makes no sense, so the tick (not the ring) is the honest symbol.
Three mistakes the symbols catch
- Foreign key on the wrong side. The foot always lands on the table holding the foreign key. If your "many" end has no FK column behind it, the diagram lies.
- Missing rings. A nullable column drawn with mandatory ticks - or
the reverse. The ring is the difference between
NULLandNOT NULL, so it's worth getting right. - Feet on both ends. Many-to-many can't be drawn with one line - it needs a junction table in the middle, as covered in the schema-in-FigJam walkthrough.
Steal this
Cheat-sheet version for your next design review: one tick = one, foot = many, ring = optional, zero allowed, no ring = required. If you can read the line as an English sentence, the notation is right.
Sketching this in FigJam, FigSchema draws the crow's foot for you - drag between two exact columns, pick the cardinality, and the symbols stay glued to the right rows while the diagram moves. Free, and offline.