Understanding Database Relationships

Database Relationships: 1:1, 1:N, and M:N

Relational databases, like PostgreSQL, MySQL, and SQL Server, are built on the principle of storing data across multiple tables and defining relationships between them. These relationships are the backbone of a well-structured database, ensuring data integrity and preventing redundancy.

Understanding the three primary types of relationships—One-to-One (1:1), One-to-Many (1:N), and Many-to-Many (M:N)—is fundamental to database design.


A One-to-One (1:1) relationship means that a single record in the first table is linked to at most one record in the second table, and vice-versa.

While it’s rare to split data that is strictly 1:1, it’s typically done for reasons like:

  • Performance: Isolating a small, frequently-accessed subset of data from a large table.
  • Security: Separating sensitive data (like a password hash) into a different table with tighter access controls.
  • Clarity: Storing optional or rarely used attributes separately.

Consider a scenario where a User has a single, optional Profile (containing their bio, for instance).

erDiagram
    USER ||--o| USER_PROFILE : "has"

    USER {
        int user_id PK
        string username
        string email
    }

    USER_PROFILE {
        int profile_id PK
        int user_id FK
        text bio
        string location
    }

In this case, the user_id in the USER_PROFILE table serves as both the Foreign Key (FK) back to USER and must be declared as UNIQUE (or part of a unique index) to enforce the 1:1 constraint.


The One-to-Many (1:N) relationship is the most common type. It means that a single record in the “One” table can be associated with zero, one, or multiple records in the “Many” table, but a record in the “Many” table can only be associated with one record in the “One” table.

The relationship is established by placing a Foreign Key (FK) in the “Many” table that references the Primary Key (PK) of the “One” table.

A Department can have many Employees, but each Employee works for only one Department.

erDiagram
    DEPARTMENT ||--o{ EMPLOYEE : "manages"

    DEPARTMENT {
        int dept_id PK
        string name
    }

    EMPLOYEE {
        int emp_id PK
        string first_name
        string last_name
        int dept_id FK
        date hire_date
    }

Here, the dept_id in the EMPLOYEE table links each employee back to their respective department. This FK does not need to be unique.


A Many-to-Many (M:N) relationship exists when a record in the first table can be associated with multiple records in the second table, and a record in the second table can also be associated with multiple records in the first table.

You cannot directly implement an M:N relationship in a relational database. It must be resolved into two 1:N relationships using a third table, often called a Junction Table, Join Table, or Associative Table.

A Student can enroll in multiple Courses, and a Course can have multiple Students.

The solution is the ENROLLMENT table.

erDiagram
    STUDENT ||--o{ ENROLLMENT : "has"

    STUDENT {
        int student_id PK
        string name
    }

    COURSE ||--o{ ENROLLMENT : "offered_in"

    COURSE {
        int course_id PK
        string title
    }

    ENROLLMENT {
        int student_id PK, FK
        int course_id PK, FK
        date enrollment_date
        string grade
    }

The ENROLLMENT table’s primary key is a composite key consisting of both student_id and course_id. This structure ensures that each student-course pairing is unique and allows for the storage of attributes specific to the relationship (like grade or enrollment_date).