Atlas
  • All-in-one
  • Solutions
  • Compare
  • Pricing
PricingGet started
All guides
July 11, 2026·10 min read·database design, relationships, cardinality, junction table

One-to-Many and Many-to-Many Relationships Explained

Cardinality decides where foreign keys and junction tables live. This guide explains one-to-one, one-to-many, and many-to-many relationships and how to implement each correctly.

Almost every relationship between two tables is one of three shapes: one-to-one, one-to-many, or many-to-many. Knowing which shape you are dealing with is not academic; it directly determines where the foreign keys go and whether you need an extra table. Get the cardinality right and the implementation is mechanical. Get it wrong and you end up either unable to store the data you need or forcing awkward workarounds that fight the database at every query.

This guide explains all three cardinalities and, crucially, how each maps to actual tables and keys. Many-to-many gets the most attention because it is the one that requires a junction table and the one beginners most often stumble on. You can model these relationships visually in the editor at /diagrams or the ERD tooling at /diagram-tools/erd-tool, where the crow's foot symbols make the cardinality explicit.

One-to-one: the rare case

A one-to-one relationship means each instance of entity A relates to at most one instance of entity B, and vice versa. Each User has exactly one UserProfile, and each UserProfile belongs to exactly one User. These are genuinely uncommon, and when you find one, the first question to ask is whether the two entities should simply be a single table, since one-to-one data can usually be merged without loss.

There are legitimate reasons to keep a one-to-one split. You might separate rarely-accessed or large columns (a user's long biography and avatar blob) from the frequently-queried core row for performance. You might isolate sensitive data (payment details) into its own table with tighter access controls. When you do keep them separate, implement the relationship with a foreign key on one side carrying a UNIQUE constraint, which enforces the "at most one" on both ends. The unique constraint is what distinguishes a one-to-one from a one-to-many at the schema level.

One-to-many: the common case

The one-to-many relationship is the backbone of relational design. One Customer has many Orders; one Order has many LineItems; one BlogPost has many Comments. The "one" side is the parent, the "many" side is the child, and the implementation rule is simple and universal: put a foreign key on the many side pointing at the one side. Each Order row carries a customer_id; each Comment row carries a post_id. There is no junction table and no ambiguity.

The direction of the foreign key is worth internalizing because beginners sometimes try to put a list of order IDs on the Customer, which does not work in a relational database, columns hold single values, not lists. The child points to the parent, always. Whether the foreign key is nullable expresses the optionality: a nullable customer_id would allow an order with no customer, while NOT NULL requires every order to have one. This is exactly the minimum-participation decision that crow's foot notation captures on the diagram.

Many-to-many and the junction table

A many-to-many relationship means instances on both sides can relate to many on the other. A Student enrolls in many Courses, and each Course has many Students. An Order contains many Products, and each Product appears on many Orders. You cannot implement this with a foreign key on either side, because that would only capture one direction and still only allow a single value. The solution is a third table, called a junction table (also associative, bridge, or link table), that sits between the two.

The junction table holds one row per pairing, with a foreign key to each side. An Enrollment table has a student_id and a course_id; each row means "this student is in this course." The combination of the two foreign keys is typically the primary key, which also prevents duplicate pairings. The junction table is often more than plumbing: it is the natural home for attributes of the relationship itself, like an enrollment_date or a grade, which belong to the pairing rather than to either the student or the course alone. Recognizing when you need a junction table, and that it can carry its own data, is one of the most useful instincts in database design.

A quick decision guide

When you face two entities and need to connect them, a short set of questions gets you to the right implementation every time.

  • Can each side have many of the other? If yes, it is many-to-many: create a junction table.
  • Can only one side have many? It is one-to-many: put a foreign key on the many side.
  • Does each side have at most one of the other? It is one-to-one: foreign key with a UNIQUE constraint, or merge the tables.
  • For one-to-many, the foreign key always lives on the child (many) side, never as a list on the parent.
  • For many-to-many, make the pair of foreign keys the junction table's primary key to block duplicates.
  • If the relationship itself has attributes (a date, a role, a quantity), they belong in the junction table.
  • Use nullability on the foreign key to express whether participation is optional or mandatory.

Keep reading

  • Best Diagramming Software in 2026: The Overall Buyer Guide
  • How to Make Diagrams for Confluence
  • How to Make Diagrams for Notion
  • Free PDF tools
  • The all-in-one work OS

FAQ

Questions, answered.

Where does the foreign key go in a one-to-many relationship?
On the many (child) side, pointing at the one (parent) side. Each order carries a customer_id, each comment carries a post_id. You cannot store a list of child IDs on the parent, because a relational column holds a single value.
What is a junction table?
A junction table (also called associative, bridge, or link table) implements a many-to-many relationship. It holds one row per pairing, with a foreign key to each of the two related tables, and the combination of those keys is usually its primary key.
Why can't a many-to-many relationship use a simple foreign key?
A foreign key column holds a single value, so it can capture only one relationship per row and only one direction. A many-to-many relationship needs to record many pairings on both sides, which requires a separate junction table with a row per pairing.
When should I use a one-to-one relationship?
Rarely. One-to-one data can usually be merged into a single table. Keep it split only for good reasons, such as separating large or rarely-used columns for performance, or isolating sensitive data with tighter access. Implement it with a foreign key plus a UNIQUE constraint.
Can a junction table have its own columns?
Yes, and often it should. Attributes that belong to the relationship itself, such as an enrollment date, a grade, or a quantity, live naturally in the junction table because they describe the pairing rather than either entity alone.

Ready when you are

One workspace, not ten.

Atlas replaces the stack with one platform for tasks, projects, CRM, contracts, e-signature, PDF tools, and analytics. Start free.

Get started freeSee pricing
AtlasWork, planned itself.

The AI-native, all-in-one work platform. Tasks, projects, CRM, contracts, and analytics in one calm workspace.

All systems operational
  • SOC 2 II
  • ISO 27001
  • HIPAA
  • GDPR

Product

  • Overview
  • PDF tools
  • People & HR
  • Integrations
  • Marketplace
  • Pricing

Resources

  • Guides
  • Docs
  • API reference
  • Support
  • Changelog
  • Status

Company

  • About
  • Careers
  • Press
  • Contact

Legal & trust

  • Trust center
  • Security
  • Privacy
  • Terms
  • DPA
  • GDPR
  • SLA
  • Refunds
Atlas, a product by wrxstack.com·© 2026 wrxstack·All rights reserved
PrivacyTermsSecurityStatus