Handling many-to-many relationships in PostgreSQL using Prisma is straightforward and efficient. Prisma can manage both implicit and explicit many-to-many relations.
1. Implicit Many-to-Many Relation
model User {
id Int @id @default(autoincrement())
name String
projects Project[] // Many-to-many relation
}
model Project {
id Int @id @default(autoincrement())
title String
users User[] // Many-to-many relation
}
By declaring each side as a list of the other, Prisma knows to spin up a hidden join table for you.
Generated SQL Migration
When you run prisma migrate dev, Prisma will produce SQL akin to:
-- 1. Create the two main tables
CREATE TABLE "User" (
"id" SERIAL PRIMARY KEY,
"name" TEXT NOT NULL
);
CREATE TABLE "Project" (
"id" SERIAL PRIMARY KEY,
"title" TEXT NOT NULL
);
-- 2. Create the hidden join table
CREATE TABLE "_UserToProject" (
"A" INTEGER NOT NULL,
"B" INTEGER NOT NULL,
PRIMARY KEY ("A","B"),
FOREIGN KEY ("A") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY ("B") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE
);
Key points:
The join table is named by alphabetically sorted model names with an underscore prefix: _To.
Columns are auto‑named "A"/"B"; you never interact with them directly in Prisma Client.
ON DELETE CASCADE ensures that if a User (or Project) is deleted, all linking rows vanish automatically.
Example 2
Here you can see many to many relation in between User and Team,
Team and Project. the joining table for this schema will be created by prisma automatically.
model User {
id String @id @default(cuid())
email String @unique
username String @unique
password String
projects Project[]
teams Team[]
}
model Project {
id String @id @default(cuid())
name String
creatorId String @map("creator_id")
creator User @relation(fields: [creatorId], references: [id])
teams Team[]
}
model Team {
id String @id @default(cuid())
name String?
creatorId String @map("creator_id")
users User[]
projects Project[]
}
implicit handling of many to many relations in prisma is more easier than manually creating a joining table.
but it lacks in flexibility, like in above example user and team have many to many relation, we can not add more field describing additional information about this relation like role of the user in related team.
2.Explicit Many to Many Relations
In Explicit Many to Many Relations you have to manually create a join table for tow models.
in this example i created two join tables UserTeam and ProjectTeam.
model User {
id String @id @default(cuid())
email String @unique
username String @unique
password String
projects Project[]
teams UserTeam[]
}
model Project {
id String @id @default(cuid())
name String
creatorId String @map("creator_id")
creator User @relation(fields: [creatorId], references: [id])
teams ProjectTeam[]
}
model Team {
id String @id @default(cuid())
name String?
creatorId String @map("creator_id")
users UserTeam[]
projects ProjectTeam[]
}
model UserTeam {
id String @id @default(cuid())
teamId String
userId String
team Team @relation(fields: [teamId], references: id)
user User @relation(fields: [userId], references: id)
}
model ProjectTeam {
id String @id @default(cuid())
teamId String
userId String
team Team @relation(fields: [teamId], references: id)
Project Project @relation(fields: [userId], references: id)
}
this manual implementation for joining tables add more flexibility in defining schema, since we can add more fields in join table that does not possible with implicit relations.
example we can add role for the user in team
model UserTeam {
id String @id @default(cuid())
teamId String
userId String
role String
team Team @relation(fields: [teamId], references: id)
user User @relation(fields: [userId], references: id)
}
💡Conclusion:
choosing between implicit and explicit relational handling is depend upon you project requirement. if you require simpler many to many link between two models or don't need extra data on relation itself then you should go with implicit handling.
if your project require flexibility in schema , to add more data on relation itself, you should try creating a joining table explicitly to handle many to many relation.
Reference:
Prisma Documentation: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/many-to-many-relations
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.