🧙‍♂️《Next Full-stack 的魔法日记》

第 0x07 章:Prisma 数据迁移 & 种子数据 ------ "把大象塞进冰箱"的优雅姿势

📚 目录(点击可直接瞬移)

  1. 🧬 迁移的本质:从 0 到 1,再从 1 到 ∞
  2. 🚧 迁移三步曲:migrate devmigrate deploydb push
  3. 🌱 种子数据:给数据库撒一把"魔法豆"
  4. 🎩 实战:把大象(schema)塞进冰箱(PostgreSQL)
  5. 🔥 踩坑急救包:当 migrate deploy 甩你一脸 ERROR
  6. 🧩 彩蛋:让种子数据自带"表情包"

1. 🧬 迁移的本质:从 0 到 1,再从 1 到 ∞

"在 SQLite 里,你可以随时 rm -rf dev.db

但在生产 PostgreSQL,你敢 DROP DATABASE production

恭喜,DevOps 会把你做成刺身。"

数据库迁移(Migration)的本质是------
把「意图」翻译成「可重放的 SQL 脚本」

就像把产品经理的 "我要一个五彩斑斓的黑" 翻译成 ALTER TABLE ... ADD COLUMN color VARCHAR(7) DEFAULT '#000000';

Prisma 的魔法在于:

  • 声明式 schema 描述意图
  • 版本化 SQL 文件 记录步骤
  • 可回滚事务 保证原子性

2. 🚧 迁移三步曲

命令 适用场景 底层干的脏活累活
prisma migrate dev 本地开发 计算 diff → 生成 SQL → 执行 → 写入 _prisma_migrations
prisma migrate deploy CI/CD 只做"执行"不做"diff",保证幂等
prisma db push 快速原型 直接 CREATE TABLE IF NOT EXISTS不生成迁移文件(⚠️ 高危)

可以把它们想成:

  • migrate dev边开车边修路
  • migrate deploy高铁准点发车
  • db pushF1 换轮胎------快,但容易着火

3. 🌱 种子数据:给数据库撒一把"魔法豆"

"没有种子的数据库,就像没有彩蛋的游戏------能跑,但索然无味。"

Prisma 官方推荐把种子脚本放在 prisma/seed.js,并在 package.json 声明:

json 复制代码
"prisma": {
  "seed": "node prisma/seed.js"
}

运行方式:

bash 复制代码
npx prisma db seed   # 等价于 node prisma/seed.js

4. 🎩 实战:把大象塞进冰箱

Step 1:初始化项目

bash 复制代码
npx create-next-app@latest next-prisma-magic --typescript --tailwind --eslint
cd next-prisma-magic
npm install prisma @prisma/client
npx prisma init

Step 2:schema.prisma ------ 描述我们的"大象"

prisma 复制代码
// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Wizard {
  id        Int      @id @default(autoincrement())
  name      String
  spell     String
  manaCost  Int
  createdAt DateTime @default(now())
}

🖼️ 示意图:一只穿长袍的大象,手里拿着魔杖,旁边写着 "Wizard"。

Step 3:创建 .env 并连上 PostgreSQL

bash 复制代码
# .env
DATABASE_URL="postgresql://magic_user:secret@localhost:5432/magic_db"

Step 4:第一次迁移

bash 复制代码
npx prisma migrate dev --name init_wizard_table

执行后,Prisma 会:

  1. 计算 schema 与数据库的差异
  2. 生成 prisma/migrations/20250822120000_init_wizard_table/migration.sql
  3. _prisma_migrations 表插入一条记录(类似 Git 的 commit hash)

Step 5:撒种子 ------ prisma/seed.js

js 复制代码
// prisma/seed.js
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()

async function main() {
  const gandalf = await prisma.wizard.upsert({
    where: { id: 1 },
    update: {},
    create: {
      name: 'Gandalf',
      spell: 'You shall not pass!',
      manaCost: 9000,
    },
  })

  const merlin = await prisma.wizard.upsert({
    where: { id: 2 },
    update: {},
    create: {
      name: 'Merlin',
      spell: 'Abracadabra',
      manaCost: 42,
    },
  })

  console.table([gandalf, merlin])
}

main()
  .catch(e => {
    console.error('💥 种子爆炸:', e)
    process.exit(1)
  })
  .finally(async () => {
    await prisma.$disconnect()
  })

跑种子:

bash 复制代码
npx prisma db seed

控制台输出:

lua 复制代码
┌---------┬----┬---------┬-------------------------┬----------┐
│ (index) │ id │  name   │         spell           │ manaCost │
├---------┼----┼---------┼-------------------------┼----------┤
│    0    │ 1  │ Gandalf │ 'You shall not pass!'   │   9000   │
│    1    │ 2  │ Merlin  │ 'Abracadabra'           │    42    │
└---------┴----┴---------┴-------------------------┴----------┘

5. 🔥 踩坑急救包

症状 病因 解药
migrate deployP3009 数据库 schema 与迁移历史不一致 先用 migrate resolve --rolled-back 回滚,再重跑
种子脚本跑两次导致唯一键冲突 没用 upsert 或缺少 where create 改成 upsert
CI 上 DATABASE_URL 没读到 GitHub Actions 没配置 Secret 在仓库 → Settings → Secrets and variables → Actions 里加

6. 🧩 彩蛋:让种子数据自带"表情包"

seed.js 里加点小彩蛋:

js 复制代码
const spells = [
  { name: 'Dobby', spell: '🧦 Dobby is free!', manaCost: 1 },
  { name: 'Hermione', spell: "📚 It's leviOsa, not levioSA!", manaCost: 1337 },
]

for (const s of spells) {
  await prisma.wizard.create({ data: s })
}

运行后,数据库里就会出现一行行会眨眼的 emoji,

SELECT * FROM wizard 的查询结果像弹幕一样欢快。


🏁 结语

恭喜你!

现在你已经掌握了把大象(schema)塞进冰箱(PostgreSQL)的优雅姿势,

还顺手给冰箱贴上了会动的冰箱贴(种子数据)。

下一章,我们将用 Next.js 13 的 App Router + Server Actions 把魔杖交到前端手里。

敬请期待 ------

"前端:我要一个五彩斑斓的黑。

后端:给你返回 #000000

全栈:给你返回 #000000 并附赠 box-shadow: 0 0 20px #bada55;"


🔮 彩蛋口令:在评论区打出 prisma migrate dev --create-only 召唤一次"只生成 SQL 不执行"的魔法!

相关推荐
吃杠碰小鸡5 分钟前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone11 分钟前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_090130 分钟前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农42 分钟前
Vue 2.3
前端·javascript·vue.js
夜郎king1 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳1 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵2 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星2 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_2 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝2 小时前
RBAC前端架构-01:项目初始化
前端·架构