🧙‍♂️《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 不执行"的魔法!

相关推荐
Dragon Wu18 分钟前
前端 下载后端返回的二进制excel数据
前端·javascript·html5
北海几经夏24 分钟前
React响应式链路
前端·react.js
晴空雨1 小时前
React Media 深度解析:从使用到 window.matchMedia API 详解
前端·react.js
一个有故事的男同学1 小时前
React性能优化全景图:从问题发现到解决方案
前端
探码科技1 小时前
2025年20+超实用技术文档工具清单推荐
前端
Juchecar1 小时前
Vue 3 推荐选择组合式 API 风格(附录与选项式的代码对比)
前端·vue.js
uncleTom6661 小时前
# 从零实现一个Vue 3通用建议选择器组件:设计思路与最佳实践
前端·vue.js
影i1 小时前
iOS WebView 异步跳转解决方案
前端
Nicholas681 小时前
flutter滚动视图之ScrollController源码解析(三)
前端
爪洼守门员1 小时前
安装electron报错的解决方法
前端·javascript·electron