DEV Community

Harsh Mishra
Harsh Mishra

Posted on

Understanding Relationships in MySQL and Prisma

Understanding Relationships in MySQL and Prisma

Introduction

In relational databases like MySQL, defining relationships between tables is essential for structuring data efficiently. There are three main types of relationships: One-to-One (1:1), One-to-Many (1:M), and Many-to-Many (M:N). Each type requires a specific table structure, foreign key constraints, and query approach.

In this article, we will explore:

  • How to define relationships in MySQL with SQL table schemas.
  • How to query related data using SQL.
  • How to model the same relationships in Prisma ORM.
  • How to retrieve related data using Prisma queries.

By the end, you’ll have a solid understanding of how to manage relational data efficiently with MySQL and Prisma. 🚀

1. Types of Relations in MySQL

In MySQL, relationships between tables are typically categorized into three main types:

  1. One-to-One (1:1)
  2. One-to-Many (1:M)
  3. Many-to-Many (M:N)

For each relation, I will explain:

  • Table Schema in MySQL
  • Querying the Relationship in SQL
  • How to Define It in Prisma Schema
  • Querying the Relationship in Prisma
  • Example Output

2. One-to-One (1:1) Relationship

Example Scenario

A User can have one Profile, and a Profile belongs to only one User.

MySQL Table Schema

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

CREATE TABLE profiles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    bio TEXT,
    user_id INT UNIQUE,  -- Ensures one-to-one relationship
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
Enter fullscreen mode Exit fullscreen mode

Querying in MySQL (Fetching User with Profile)

SELECT users.id, users.name, profiles.bio
FROM users
LEFT JOIN profiles ON users.id = profiles.user_id;
Enter fullscreen mode Exit fullscreen mode

Example Output

id name bio
1 John Loves coding
2 Alice Enjoys music

Defining One-to-One in Prisma Schema

model User {
  id      Int      @id @default(autoincrement())
  name    String
  profile Profile?
}

model Profile {
  id     Int    @id @default(autoincrement())
  bio    String?
  user   User   @relation(fields: [userId], references: [id])
  userId Int    @unique
}
Enter fullscreen mode Exit fullscreen mode

Querying in Prisma

const userWithProfile = await prisma.user.findMany({
  include: { profile: true }
});
console.log(userWithProfile);
Enter fullscreen mode Exit fullscreen mode

Example Output in Prisma

[
  { "id": 1, "name": "John", "profile": { "bio": "Loves coding" } },
  { "id": 2, "name": "Alice", "profile": { "bio": "Enjoys music" } }
]
Enter fullscreen mode Exit fullscreen mode

3. One-to-Many (1:M) Relationship

Example Scenario

A User can have many Posts, but each Post belongs to only one User.

MySQL Table Schema

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    content TEXT,
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
Enter fullscreen mode Exit fullscreen mode

Querying in MySQL (Fetching User with Posts)

SELECT users.id, users.name, posts.title
FROM users
LEFT JOIN posts ON users.id = posts.user_id;
Enter fullscreen mode Exit fullscreen mode

Example Output

id name title
1 John MySQL Guide
1 John Prisma Intro
2 Alice Music Life

Defining One-to-Many in Prisma Schema

model User {
  id    Int     @id @default(autoincrement())
  name  String
  posts Post[]
}

model Post {
  id      Int    @id @default(autoincrement())
  title   String
  content String?
  user    User   @relation(fields: [userId], references: [id])
  userId  Int
}
Enter fullscreen mode Exit fullscreen mode

Querying in Prisma

const usersWithPosts = await prisma.user.findMany({
  include: { posts: true }
});
console.log(usersWithPosts);
Enter fullscreen mode Exit fullscreen mode

Example Output in Prisma

[
  {
    "id": 1,
    "name": "John",
    "posts": [
      { "title": "MySQL Guide", "content": "MySQL is great!" },
      { "title": "Prisma Intro", "content": "Prisma is awesome!" }
    ]
  },
  {
    "id": 2,
    "name": "Alice",
    "posts": [{ "title": "Music Life", "content": "I love music" }]
  }
]
Enter fullscreen mode Exit fullscreen mode

4. Many-to-Many (M:N) Relationship

Example Scenario

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

MySQL Table Schema

CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

CREATE TABLE courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL
);

CREATE TABLE enrollments (
    student_id INT,
    course_id INT,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE,
    FOREIGN KEY (course_id) REFERENCES courses(id) ON DELETE CASCADE
);
Enter fullscreen mode Exit fullscreen mode

Querying in MySQL (Fetching Students with Courses)

SELECT students.name, courses.title
FROM enrollments
JOIN students ON enrollments.student_id = students.id
JOIN courses ON enrollments.course_id = courses.id;
Enter fullscreen mode Exit fullscreen mode

Example Output

name title
John Math 101
John Physics 201
Alice Math 101

Defining Many-to-Many in Prisma Schema

model Student {
  id         Int       @id @default(autoincrement())
  name       String
  courses    Course[]  @relation("Enrollments")
}

model Course {
  id         Int       @id @default(autoincrement())
  title      String
  students   Student[] @relation("Enrollments")
}

model Enrollment {
  student   Student @relation(fields: [studentId], references: [id])
  studentId Int
  course    Course  @relation(fields: [courseId], references: [id])
  courseId  Int

  @@id([studentId, courseId])
}
Enter fullscreen mode Exit fullscreen mode

Querying in Prisma

const studentsWithCourses = await prisma.student.findMany({
  include: { courses: true }
});
console.log(studentsWithCourses);
Enter fullscreen mode Exit fullscreen mode

Example Output in Prisma

[
  { "name": "John", "courses": [{ "title": "Math 101" }, { "title": "Physics 201" }] },
  { "name": "Alice", "courses": [{ "title": "Math 101" }] }
]
Enter fullscreen mode Exit fullscreen mode

5. Summary Table

Relationship MySQL Schema SQL Query Prisma Schema Prisma Query
One-to-One user_id UNIQUE in second table JOIN ON user_id User has Profile? include: { profile: true }
One-to-Many Foreign key in child table JOIN ON user_id User has Post[] include: { posts: true }
Many-to-Many Junction table with two FKs JOIN through junction Student[] - Course[] include: { courses: true }

Conclusion

  • MySQL uses foreign keys and junction tables to define relationships.
  • Prisma uses a declarative schema to simplify relationship management.
  • Querying relationships in Prisma is easy using include.
  • Output in Prisma is structured as JSON, making it easy to work with.

Top comments (0)