1. Prisma 的核心结构
你只需要记住:
prisma.模型名.方法()
比如:
prisma.user.findMany()
prisma.word.create()
prisma.post.update()
如果你的模型是:
model Word {
id Int @id @default(autoincrement())
text String
meaning String
level String
}
那么生成的 API 就是:
prisma.word.findMany()
prisma.word.create()
prisma.word.update()
prisma.word.delete()
注意:模型 Word,调用时是小写 word。
2. 查:findMany / findUnique / findFirst
查询全部
const words = await prisma.word.findMany()
按唯一字段查
const word = await prisma.word.findUnique({
where: {
id: 1,
},
})
适合查:
id
email
slug
这类唯一字段。
查第一个符合条件的
const word = await prisma.word.findFirst({
where: {
level: 'G1',
},
})
区别:
findUnique:只能用唯一字段
findFirst:普通条件也可以
findMany:返回数组
3. 增:create / createMany
创建一条
const word = await prisma.word.create({
data: {
text: 'apple',
meaning: '苹果',
level: 'G1',
},
})
批量创建
await prisma.word.createMany({
data: [
{ text: 'apple', meaning: '苹果', level: 'G1' },
{ text: 'banana', meaning: '香蕉', level: 'G1' },
],
})
跳过重复数据
前提是字段有 @unique。
model Word {
id Int @id @default(autoincrement())
text String @unique
meaning String
level String
}
await prisma.word.createMany({
data: [
{ text: 'apple', meaning: '苹果', level: 'G1' },
],
skipDuplicates: true,
})
4. 改:update / updateMany / upsert
修改一条
await prisma.word.update({
where: {
id: 1,
},
data: {
meaning: '苹果;苹果树',
},
})
批量修改
await prisma.word.updateMany({
where: {
level: 'G1',
},
data: {
level: 'Grade1',
},
})
有就更新,没有就创建:upsert
这个很重要,适合导入词库。
await prisma.word.upsert({
where: {
text: 'apple',
},
update: {
meaning: '苹果',
level: 'G1',
},
create: {
text: 'apple',
meaning: '苹果',
level: 'G1',
},
})
5. 删:delete / deleteMany
删除一条
await prisma.word.delete({
where: {
id: 1,
},
})
按条件批量删除
await prisma.word.deleteMany({
where: {
level: 'test',
},
})
危险操作:
await prisma.word.deleteMany()
这会清空整张表。
6. 条件查询 where
等于
where: {
level: 'G1'
}
不等于
where: {
level: {
not: 'G1',
},
}
包含
where: {
text: {
contains: 'app',
},
}
开头匹配
where: {
text: {
startsWith: 'a',
},
}
结尾匹配
where: {
text: {
endsWith: 'e',
},
}
大于 / 小于
where: {
id: {
gt: 10,
},
}
常用:
gt // 大于
gte // 大于等于
lt // 小于
lte // 小于等于
多条件 AND
where: {
AND: [
{ level: 'G1' },
{ text: { contains: 'a' } },
],
}
其实这样也默认是 AND:
where: {
level: 'G1',
text: {
contains: 'a',
},
}
OR
where: {
OR: [
{ level: 'G1' },
{ level: 'G2' },
],
}
NOT
where: {
NOT: {
level: 'G1',
},
}
7. 排序 orderBy
const words = await prisma.word.findMany({
orderBy: {
id: 'desc',
},
})
多个排序:
const words = await prisma.word.findMany({
orderBy: [
{ level: 'asc' },
{ id: 'desc' },
],
})
8. 分页 take / skip
第 1 页,每页 10 条
const page = 1
const pageSize = 10
const words = await prisma.word.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
})
第 2 页
const words = await prisma.word.findMany({
skip: 10,
take: 10,
})
这叫 offset 分页,适合后台管理。
9. 游标分页 cursor
适合 App 信息流、单词列表、无限滚动。
const words = await prisma.word.findMany({
take: 10,
cursor: {
id: 100,
},
skip: 1,
orderBy: {
id: 'asc',
},
})
意思是:
从 id = 100 后面开始,再取 10 条
10. select:只返回指定字段
const words = await prisma.word.findMany({
select: {
id: true,
text: true,
meaning: true,
},
})
返回:
[
{ id: 1, text: 'apple', meaning: '苹果' }
]
不会返回 level。
这是性能优化重点。
11. include:查询关联数据
假设你的表是:
model Word {
id Int @id @default(autoincrement())
text String
meaning String
level String
sentences Sentence[]
}
model Sentence {
id Int @id @default(autoincrement())
content String
wordId Int
word Word @relation(fields: [wordId], references: [id])
}
查询单词时带上句子:
const words = await prisma.word.findMany({
include: {
sentences: true,
},
})
返回结构类似:
[
{
id: 1,
text: 'apple',
meaning: '苹果',
level: 'G1',
sentences: [
{ id: 1, content: 'I eat an apple.' }
]
}
]
12. include + select 组合
const words = await prisma.word.findMany({
select: {
id: true,
text: true,
sentences: {
select: {
id: true,
content: true,
},
},
},
})
这才是生产项目里最常用的写法。
13. 关系过滤 some / every / none
查询“有例句的单词”:
const words = await prisma.word.findMany({
where: {
sentences: {
some: {},
},
},
})
查询“没有例句的单词”:
const words = await prisma.word.findMany({
where: {
sentences: {
none: {},
},
},
})
查询“至少有一个例句包含 apple 的单词”:
const words = await prisma.word.findMany({
where: {
sentences: {
some: {
content: {
contains: 'apple',
},
},
},
},
})
14. 嵌套创建 nested create
创建单词时,同时创建句子:
await prisma.word.create({
data: {
text: 'apple',
meaning: '苹果',
level: 'G1',
sentences: {
create: [
{ content: 'I eat an apple.' },
{ content: 'This is a red apple.' },
],
},
},
})
这非常适合你的英语学习 App。
15. connect:关联已有数据
假设已有一个 Word,现在创建句子并关联它:
await prisma.sentence.create({
data: {
content: 'I like apples.',
word: {
connect: {
id: 1,
},
},
},
})
等价于直接写:
await prisma.sentence.create({
data: {
content: 'I like apples.',
wordId: 1,
},
})
16. count:统计数量
const count = await prisma.word.count()
带条件:
const count = await prisma.word.count({
where: {
level: 'G1',
},
})
分页接口经常这样写:
const [list, total] = await Promise.all([
prisma.word.findMany({
skip: 0,
take: 10,
}),
prisma.word.count(),
])
17. 聚合 aggregate
const result = await prisma.word.aggregate({
_count: {
id: true,
},
_max: {
id: true,
},
_min: {
id: true,
},
})
常用于统计。
18. 分组 groupBy
按等级统计单词数量:
const result = await prisma.word.groupBy({
by: ['level'],
_count: {
id: true,
},
})
返回类似:
[
{ level: 'G1', _count: { id: 300 } },
{ level: 'G2', _count: { id: 450 } }
]
19. 事务 $transaction
写法一:数组事务
await prisma.$transaction([
prisma.word.create({
data: {
text: 'apple',
meaning: '苹果',
level: 'G1',
},
}),
prisma.word.create({
data: {
text: 'banana',
meaning: '香蕉',
level: 'G1',
},
}),
])
意思是:
要么全部成功
要么全部失败
写法二:函数事务
await prisma.$transaction(async (tx) => {
const word = await tx.word.create({
data: {
text: 'apple',
meaning: '苹果',
level: 'G1',
},
})
await tx.sentence.create({
data: {
content: 'I eat an apple.',
wordId: word.id,
},
})
})
适合前后操作有依赖关系的场景。
20. 原生 SQL:$queryRaw
Prisma 搞不定复杂 SQL 时用它。
const result = await prisma.$queryRaw`
SELECT * FROM "Word" WHERE level = ${'G1'}
`
注意:不要拼字符串。
错误写法:
await prisma.$queryRawUnsafe(
`SELECT * FROM "Word" WHERE level = '${level}'`
)
容易 SQL 注入。
21. Prisma Studio
可视化查看数据库:
npx prisma studio
打开后可以直接看表、改数据。
22. 常用 CLI 命令
npx prisma init
初始化 Prisma。
npx prisma generate
根据 schema.prisma 生成客户端。
npx prisma migrate dev --name init
开发环境创建迁移并同步数据库。
npx prisma migrate deploy
生产环境执行迁移。
npx prisma db push
直接把 schema 推到数据库,不生成 migration,适合原型开发。
npx prisma studio
打开可视化数据库管理界面。
23. schema.prisma 重点语法
主键
id Int @id @default(autoincrement())
唯一字段
email String @unique
默认值
createdAt DateTime @default(now())
更新时间
updatedAt DateTime @updatedAt
可选字段
avatar String?
枚举
enum WordLevel {
G1
G2
G3
}
model Word {
id Int @id @default(autoincrement())
text String
level WordLevel
}
索引
model Word {
id Int @id @default(autoincrement())
text String
level String
@@index([level])
}
联合唯一
model Word {
id Int @id @default(autoincrement())
text String
level String
@@unique([text, level])
}
意思是:
同一个 level 里 text 不能重复
学习顺序
第一轮:create / findMany / update / delete
第二轮:where / orderBy / skip / take
第三轮:select / include
第四轮:一对多关系
第五轮:事务
第六轮:groupBy / aggregate
第七轮:raw SQL
你的目标不是“记住所有 API”,而是形成这个反射:
我要查数据 → findMany / findUnique
我要插数据 → create / createMany
我要改数据 → update / updateMany
我要有则改无则增 → upsert
我要关联查询 → include / select
我要安全处理多步写入 → transaction
我要复杂 SQL → queryRaw