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

相关推荐
BillKu2 小时前
Vue3 + Element-Plus 抽屉关闭按钮居中
前端·javascript·vue.js
DevilSeagull2 小时前
JavaScript WebAPI 指南
java·开发语言·javascript·html·ecmascript·html5
面向星辰3 小时前
html中css的四种定位方式
前端·css·html
Async Cipher3 小时前
CSS 权重(优先级规则)
前端·css
大怪v3 小时前
前端佬:机器学习?我也会啊!😎😎😎手“摸”手教你做个”自动驾驶“~
前端·javascript·机器学习
Liquad Li4 小时前
Angular 面试题及详细答案
前端·angular·angular.js
用户21411832636024 小时前
首发!即梦 4.0 接口开发全攻略:AI 辅助零代码实现,开源 + Docker 部署,小白也能上手
前端
gnip6 小时前
链式调用和延迟执行
前端·javascript
SoaringHeart6 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.6 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频