多对多关系
多对多 (m-n) 关系指,其中一侧的零或多条记录可以关联另一侧的零或多条记录的关系。
关系型数据库中,多对多关系一般通过 关系表 实现。Prisma schema 中多对多关系既可以是 显式的 也可以是 隐式的。
表结构
ts
model course {
id Int @id @default(autoincrement())
name String? @db.VarChar(10)
student_courses student_course[]
}
model student {
id Int @id @default(autoincrement())
name String? @db.VarChar(10)
no String? @db.VarChar(10)
student_courses student_course[]
}
model student_course {
id Int @id @default(autoincrement())
studentid Int
student student @relation(fields: [studentid], references: [id])
courseid Int
course course @relation(fields: [courseid], references: [id])
}查询
- 第一种通过
student->student_course->course查询
ts
async manybymany() {
const result = await this.prismadbService.student.findMany({
select: {
name: true,
student_courses: {
select: {
course: {
select: {
name: true,
},
},
},
},
},
});
return result;
}- 第二种通过
student_course->student或者course查询
ts
async manybymany2() {
const result = await this.prismadbService.student_course.findMany({
select: {
student: {
select: {
name: true,
},
},
course: {
select: {
name: true,
},
},
},
});
return result;
}有的时候需要把关联的全部查询
ts
const list = await this.prisma.users.findMany({
include: {
user_roles: {
select: {
role_id: true,
},
},
},
});插入语法
场景说明
学生表 student 和课程表 course 是多对多关系
中间表 student_course 负责记录"哪个学生选了哪门课"
比如:张三选了 数学 和 英语 两门课
方式一:嵌套创建(一次性全建好)
学生和课程都不存在,同时创建学生、课程,并自动写入中间表
ts
async insertManyByMany() {
const result = await this.prismadbService.student.create({
data: {
name: '张三',
no: 'S001',
student_courses: {
create: [
// 每一条 create 都会往中间表 student_course 插一条记录
{
course: {
create: { name: '数学' }, // 同时新建课程
},
},
{
course: {
create: { name: '英语' },
},
},
],
},
},
});
return result;
}说明
student_courses: { create: [...] } 就是往中间表插数据
中间表的 studentid 由 Prisma 自动填,course 里面的 create 表示同时新建课程
方式二:连接已有数据(connect)
学生已存在,要给他选一门已经存在的课程(比如 id 为 1 的数学课)
ts
async insertConnect() {
const result = await this.prismadbService.student.update({
where: { id: 1 }, // 找到 id 为 1 的学生
data: {
student_courses: {
create: [
{
course: {
connect: { id: 1 }, // 连接到已存在的课程
},
},
],
},
},
});
return result;
}create 和 connect 的区别
create:课程不存在,新建课程并关联connect:课程已存在,直接关联过去
方式三:直接操作中间表(最简单直白)
如果学生 id 和课程 id 都知道,直接往中间表插数据就行
ts
async insertByRelationTable() {
const result = await this.prismadbService.student_course.create({
data: {
studentid: 1, // 学生 id
courseid: 2, // 课程 id
},
});
return result;
}方式四:批量插入选课记录(createMany)
一个学生一次选了多门课,可以用 createMany 批量插入
ts
async insertMany() {
const result = await this.prismadbService.student_course.createMany({
data: [
{ studentid: 1, courseid: 1 },
{ studentid: 1, courseid: 2 },
{ studentid: 1, courseid: 3 },
],
});
return result;
}注意
注意
多对多插入本质就是往中间表
student_course写数据嵌套创建时中间表的外键(
studentid/courseid)不用自己写,Prisma 自动处理用
connect时,连接的课程必须真实存在,否则会报错createMany只能直接写外键,不支持嵌套create