Prisma数据库同步与迁移命令详解
Prisma数据库同步与迁移命令详解
学习目标:掌握 prisma db pull、prisma db seed、prisma db execute 等数据库操作命令,理解数据库同步和迁移的最佳实践。
一、Prisma 数据库命令概览
1.1 数据库相关命令一览
code
Prisma 数据库命令概览:
│
├── prisma db pull
│ ├── 作用:从数据库同步 Schema
│ ├── 场景:已有数据库,生成 Prisma Schema
│ └── 方向:Database → Schema
│
├── prisma db push
│ ├── 作用:将 Schema 同步到数据库
│ ├── 场景:原型开发、快速迭代
│ └── 方向:Schema → Database
│
├── prisma db seed
│ ├── 作用:填充初始数据
│ ├── 场景:数据库初始化、测试数据
│ └── 方向:Script → Database
│
├── prisma db execute
│ ├── 作用:执行 SQL 语句
│ ├── 场景:执行原生 SQL、批量操作
│ └── 方向:SQL → Database
│
└── prisma migrate
│ ├── 作用:数据库迁移管理
│ ├── 场景:生产环境、团队协作
│ └── 方向:Schema + Migrations → Database1.2 命令对比:db pull vs db push
| 维度 | db pull | db push |
|---|---|---|
| 方向 | Database → Schema | Schema → Database |
| 用途 | 从数据库生成 Schema | 将 Schema 同步到数据库 |
| 场景 | 已有数据库、数据库迁移 | 原型开发、快速迭代 |
| 安全性 | 只读操作,不会修改数据库 | 可能修改数据库结构 |
| 推荐 | 初始化项目时使用 | 开发环境使用 |
二、prisma db pull 命令详解
2.1 命令基本用法
bash
# 基本用法
npx prisma db pull
# 指定 Schema 文件路径
npx prisma db pull --schema=./prisma/schema.prisma
# 打印结果但不写入文件
npx prisma db pull --print
# 强制覆盖现有 Schema
npx prisma db pull --force2.2 命令参数详解
| 参数 | 说明 | 默认值 |
|---|---|---|
--schema | 指定 Schema 文件路径 | ./prisma/schema.prisma |
--print | 打印结果到控制台 | false |
--force | 强制覆盖现有 Schema | false |
--url | 指定数据库连接 URL | 使用 DATABASE_URL |
2.3 实战示例:从数据库同步 Schema
场景:修改数据库字段类型
步骤一:使用数据库管理工具修改表结构
sql
-- 在数据库管理工具中执行
-- 将 users 表的 phone 字段从 INT 改为 BIGINT
ALTER TABLE users MODIFY COLUMN phone BIGINT;步骤二:使用 db pull 同步到 Schema
bash
# 执行同步命令
npx prisma db pull
# 输出示例
Introspecting database
Writing to ./prisma/schema.prisma
Generated Prisma Schema步骤三:查看更新后的 Schema
prisma
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
username String @unique
password String
name String
phone BigInt? // 从 Int 改为 BigInt
email String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users")
}2.4 db pull 工作原理
code
prisma db pull 工作流程:
│
├── 第一步:连接数据库
│ └── 使用 DATABASE_URL 连接
│
├── 第二步:读取数据库结构
│ ├── 表结构(表名、字段名、类型)
│ ├── 索引(主键、唯一索引、普通索引)
│ ├── 外键约束
│ └── 默认值
│
├── 第三步:生成 Prisma Schema
│ ├── 转换 SQL 类型为 Prisma 类型
│ ├── 生成 model 定义
│ └── 添加关系定义
│
└── 第四步:写入 schema.prisma
└── 保存到指定路径2.5 SQL 类型到 Prisma 类型映射
| SQL 类型 | Prisma 类型 | 说明 |
|---|---|---|
INT | Int | 整数 |
BIGINT | BigInt | 大整数 |
VARCHAR(n) | String | 字符串 |
TEXT | String | 长文本 |
BOOLEAN | Boolean | 布尔值 |
DATETIME | DateTime | 日期时间 |
DECIMAL(p, s) | Decimal | 精确小数 |
FLOAT | Float | 浮点数 |
JSON | Json | JSON 数据 |
三、prisma db pull 最佳实践
3.1 使用场景一:已有数据库初始化项目
code
场景描述:
│
├── 已有数据库
│ ├── 运行中的生产数据库
│ ├── 遗留系统数据库
│ └── 第三方数据库
│
├── 需求
│ ├── 使用 Prisma 管理数据库
│ ├── 需要类型安全的查询
│ └── 不想手动编写 Schema
│
└── 解决方案
├── 使用 db pull 生成 Schema
├── 使用 prisma generate 生成 Client
└── 开始使用 Prisma Client完整流程:
bash
# 1. 创建 Prisma 项目
mkdir my-project
cd my-project
npm init -y
# 2. 安装 Prisma
npm install prisma @prisma/client
# 3. 初始化 Prisma
npx prisma init
# 4. 配置数据库连接
# 编辑 .env 文件
DATABASE_URL="mysql://user:password@localhost:3306/mydb"
# 5. 从数据库拉取 Schema
npx prisma db pull
# 6. 生成 Prisma Client
npx prisma generate
# 7. 开始使用
node index.js3.2 使用场景二:数据库迁移
code
数据库迁移场景:
│
├── 场景:MySQL → PostgreSQL
│
├── 第一步:从 MySQL 拉取 Schema
│ └── npx prisma db pull(连接 MySQL)
│
├── 第二步:调整 Schema
│ ├── 修改数据库提供者为 postgresql
│ ├── 调整不兼容的类型
│ └── 调整字段约束
│
├── 第三步:推送到 PostgreSQL
│ └── npx prisma db push(连接 PostgreSQL)
│
└── 第四步:迁移数据
├── 导出 MySQL 数据
├── 转换数据格式
└── 导入 PostgreSQL实战代码:
bash
# 步骤 1:从 MySQL 拉取 Schema
# .env
DATABASE_URL="mysql://user:password@localhost:3306/mydb"
npx prisma db pull
# 步骤 2:修改 schema.prisma
# 将 provider 从 mysql 改为 postgresql
# datasource db {
# provider = "postgresql"
# url = env("DATABASE_URL")
# }
# 步骤 3:切换到 PostgreSQL
# .env
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
# 步骤 4:推送到 PostgreSQL
npx prisma db push
# 步骤 5:迁移数据
# 使用数据迁移脚本
node migrate-data.jsjavascript
// migrate-data.js
const { PrismaClient: MySQLClient } = require('./mysql-client');
const { PrismaClient: PostgresClient } = require('./postgres-client');
const mysql = new MySQLClient();
const postgres = new PostgresClient();
async function migrateData() {
// 从 MySQL 读取数据
const users = await mysql.user.findMany();
// 写入 PostgreSQL
for (const user of users) {
await postgres.user.create({
data: user,
});
}
console.log('数据迁移完成!');
}
migrateData();3.3 使用场景三:同步生产数据库结构
code
同步生产数据库结构:
│
├── 场景
│ ├── 生产数据库有变更
│ ├── 需要同步到开发环境
│ └── 需要更新 Prisma Schema
│
├── 流程
│ ├── 第一步:从生产环境拉取 Schema
│ ├── 第二步:生成迁移文件
│ ├── 第三步:在开发环境执行迁移
│ └── 第四步:测试验证
│
└── 注意事项
├── 不要直接连接生产数据库
├── 先备份再操作
└── 使用只读副本或导出的 Schema四、prisma db seed 命令详解
4.1 命令基本用法
bash
# 基本用法
npx prisma db seed
# 查看帮助
npx prisma db seed --help4.2 配置 seed 脚本
方式一:在 package.json 中配置(推荐)
json
// package.json
{
"name": "my-project",
"version": "1.0.0",
"prisma": {
"seed": "node prisma/seed.js"
},
"scripts": {
"db:seed": "prisma db seed"
}
}方式二:在 schema.prisma 中配置
prisma
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// 注意:seed 配置建议在 package.json 中4.3 创建 seed 脚本
javascript
// prisma/seed.js
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function main() {
// 清空现有数据
await prisma.user.deleteMany();
await prisma.post.deleteMany();
await prisma.category.deleteMany();
// 创建分类
const categories = await Promise.all([
prisma.category.create({
data: { name: '技术' },
}),
prisma.category.create({
data: { name: '前端' },
}),
prisma.category.create({
data: { name: '后端' },
}),
]);
console.log('分类创建完成:', categories);
// 创建用户
const users = await Promise.all([
prisma.user.create({
data: {
username: 'john_doe',
email: 'john@example.com',
password: '$2b$10$...', // 加密后的密码
name: 'John Doe',
phone: '13800138000',
},
}),
prisma.user.create({
data: {
username: 'jane_doe',
email: 'jane@example.com',
password: '$2b$10$...',
name: 'Jane Doe',
phone: '13900139000',
},
}),
]);
console.log('用户创建完成:', users);
// 创建文章
const posts = await Promise.all([
prisma.post.create({
data: {
title: 'Prisma 入门教程',
content: 'Prisma 是一个现代化的数据库工具...',
published: true,
authorId: users[0].id,
categories: {
connect: [
{ id: categories[0].id },
{ id: categories[1].id },
],
},
},
}),
prisma.post.create({
data: {
title: 'NestJS 实战指南',
content: 'NestJS 是一个渐进式的 Node.js 框架...',
published: true,
authorId: users[1].id,
categories: {
connect: [
{ id: categories[0].id },
{ id: categories[2].id },
],
},
},
}),
]);
console.log('文章创建完成:', posts);
console.log(' 数据填充完成!');
}
main()
.catch((e) => {
console.error(' 数据填充失败:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});4.4 使用 TypeScript 编写 seed 脚本
typescript
// prisma/seed.ts
import { PrismaClient, Prisma } from '@prisma/client';
const prisma = new PrismaClient();
const userData: Prisma.UserCreateInput[] = [
{
username: 'john_doe',
email: 'john@example.com',
password: '$2b$10$...',
name: 'John Doe',
phone: '13800138000',
},
{
username: 'jane_doe',
email: 'jane@example.com',
password: '$2b$10$...',
name: 'Jane Doe',
phone: '13900139000',
},
];
const categoryData: Prisma.CategoryCreateInput[] = [
{ name: '技术' },
{ name: '前端' },
{ name: '后端' },
];
async function main() {
console.log('开始填充数据...');
// 清空现有数据
await prisma.post.deleteMany();
await prisma.user.deleteMany();
await prisma.category.deleteMany();
// 创建分类
const categories = await Promise.all(
categoryData.map((data) => prisma.category.create({ data })),
);
console.log(`创建了 ${categories.length} 个分类`);
// 创建用户
const users = await Promise.all(
userData.map((data) => prisma.user.create({ data })),
);
console.log(`创建了 ${users.length} 个用户`);
// 创建文章
const posts = await Promise.all([
prisma.post.create({
data: {
title: 'Prisma 入门教程',
content: 'Prisma 是一个现代化的数据库工具...',
published: true,
author: {
connect: { id: users[0].id },
},
categories: {
connect: [{ id: categories[0].id }, { id: categories[1].id }],
},
},
}),
prisma.post.create({
data: {
title: 'NestJS 实战指南',
content: 'NestJS 是一个渐进式的 Node.js 框架...',
published: true,
author: {
connect: { id: users[1].id },
},
categories: {
connect: [{ id: categories[0].id }, { id: categories[2].id }],
},
},
}),
]);
console.log(`创建了 ${posts.length} 篇文章`);
console.log(' 数据填充完成!');
}
main()
.catch((e) => {
console.error(' 数据填充失败:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});json
// package.json
{
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
"devDependencies": {
"ts-node": "^10.9.0",
"typescript": "^5.0.0"
}
}4.5 seed 最佳实践
code
seed 最佳实践:
│
├── 1. 数据清理
│ ├── seed 前清空现有数据
│ ├── 注意清理顺序(外键约束)
│ └── 使用 deleteMany() 批量删除
│
├── 2. 数据一致性
│ ├── 使用事务处理
│ ├── 确保关联关系正确
│ └── 处理唯一约束
│
├── 3. 环境区分
│ ├── 开发环境:测试数据
│ ├── 测试环境:模拟数据
│ └── 生产环境:初始数据(管理员等)
│
├── 4. 可重复执行
│ ├── 幂等性设计
│ ├── 避免重复插入
│ └── 使用 upsert 代替 create
│
└── 5. 错误处理
├── 捕获异常
├── 回滚事务
└── 记录日志五、prisma db execute 命令详解
5.1 命令基本用法
bash
# 执行 SQL 文件
npx prisma db execute --file=./scripts/init.sql
# 执行 SQL 语句
npx prisma db execute --stdin <<< "SELECT * FROM users"
# 指定数据库 URL
npx prisma db execute --file=./scripts/init.sql --url=mysql://user:password@localhost:3306/mydb
# 指定 Schema 文件
npx prisma db execute --file=./scripts/init.sql --schema=./prisma/schema.prisma5.2 命令参数详解
| 参数 | 说明 | 默认值 |
|---|---|---|
--file | 指定 SQL 文件路径 | - |
--stdin | 从标准输入读取 SQL | - |
--url | 指定数据库连接 URL | 使用 DATABASE_URL |
--schema | 指定 Schema 文件路径 | ./prisma/schema.prisma |
5.3 实战示例
示例一:执行初始化脚本
sql
-- scripts/init.sql
-- 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_posts_author ON posts(author_id);
-- 创建视图
CREATE VIEW active_users AS
SELECT id, username, email, name
FROM users
WHERE deleted_at IS NULL;
-- 创建存储过程
DELIMITER //
CREATE PROCEDURE GetUserPosts(IN userId INT)
BEGIN
SELECT * FROM posts WHERE author_id = userId;
END //
DELIMITER ;bash
# 执行初始化脚本
npx prisma db execute --file=./scripts/init.sql示例二:批量更新数据
sql
-- scripts/update-users.sql
-- 批量更新用户状态
UPDATE users
SET status = 'active'
WHERE last_login_at > DATE_SUB(NOW(), INTERVAL 30 DAY);
-- 批量清理过期数据
DELETE FROM sessions
WHERE expires_at < NOW();bash
# 执行批量更新
npx prisma db execute --file=./scripts/update-users.sql示例三:执行原生 SQL 查询
bash
# 查询用户数量
npx prisma db execute --stdin <<< "SELECT COUNT(*) FROM users"
# 创建新表
npx prisma db execute --stdin <<< "CREATE TABLE logs (id INT AUTO_INCREMENT PRIMARY KEY, message TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"5.4 使用场景
code
prisma db execute 使用场景:
│
├── 1. 执行原生 SQL
│ ├── 创建存储过程
│ ├── 创建触发器
│ └── 创建视图
│
├── 2. 批量数据操作
│ ├── 批量更新
│ ├── 批量删除
│ └── 数据清理
│
├── 3. 数据库初始化
│ ├── 创建索引
│ ├── 设置权限
│ └── 初始配置
│
└── 4. 数据库维护
├── 性能优化
├── 空间清理
└── 日志管理六、数据库迁移最佳实践
6.1 db pull + migrate 组合使用
code
推荐的开发流程:
│
├── 场景一:新项目开发
│ ├── 编辑 schema.prisma
│ ├── npx prisma migrate dev --name init
│ └── 生成迁移文件
│
├── 场景二:已有数据库
│ ├── npx prisma db pull
│ ├── npx prisma migrate dev --name init
│ └── 建立迁移基线
│
└── 场景三:团队协作
├── 开发者 A:修改 Schema,执行 migrate
├── 提交迁移文件到 Git
└── 开发者 B:拉取代码,执行 migrate6.2 数据库迁移流程
bash
# 完整的数据库迁移流程
# 1. 从源数据库拉取 Schema
DATABASE_URL="mysql://..." npx prisma db pull
# 2. 调整 Schema(如需要)
# 编辑 schema.prisma
# 3. 创建初始迁移
npx prisma migrate dev --name init
# 4. 导出源数据库数据
mysqldump -u user -p mydb > backup.sql
# 5. 切换到目标数据库
# 修改 .env 中的 DATABASE_URL
# 6. 推送 Schema 到目标数据库
npx prisma db push
# 7. 导入数据到目标数据库
psql -U user -d mydb < backup.sql
# 8. 验证数据
npx prisma studio6.3 数据库命令选择指南
| 场景 | 推荐命令 | 说明 |
|---|---|---|
| 新项目开发 | migrate dev | 生成迁移文件,团队协作 |
| 原型开发 | db push | 快速迭代,不生成迁移文件 |
| 已有数据库 | db pull + migrate dev | 建立迁移基线 |
| 生产环境 | migrate deploy | 只执行迁移,不生成新迁移 |
| 填充数据 | db seed | 初始化数据、测试数据 |
| 执行 SQL | db execute | 原生 SQL、特殊操作 |
七、完整实战示例
7.1 项目结构
code
my-project/
├── prisma/
│ ├── schema.prisma # Prisma Schema
│ ├── seed.js # Seed 脚本
│ └── migrations/ # 迁移文件
│ └── 20240101000000_init/
│ └── migration.sql
├── scripts/
│ ├── init.sql # 初始化 SQL
│ └── cleanup.sql # 清理 SQL
├── src/
│ └── index.js
├── .env # 环境变量
├── package.json
└── README.md7.2 package.json 配置
json
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"db:pull": "prisma db pull",
"db:push": "prisma db push",
"db:seed": "prisma db seed",
"db:execute": "prisma db execute",
"db:studio": "prisma studio",
"migrate:dev": "prisma migrate dev",
"migrate:deploy": "prisma migrate deploy",
"migrate:reset": "prisma migrate reset",
"generate": "prisma generate"
},
"prisma": {
"seed": "node prisma/seed.js"
},
"dependencies": {
"@prisma/client": "^5.0.0"
},
"devDependencies": {
"prisma": "^5.0.0"
}
}7.3 完整操作流程
bash
# 1. 安装依赖
npm install
# 2. 配置数据库连接
# 编辑 .env
DATABASE_URL="mysql://user:password@localhost:3306/mydb"
# 3. 从已有数据库拉取 Schema
npm run db:pull
# 4. 生成 Prisma Client
npm run generate
# 5. 创建初始迁移
npm run migrate:dev -- --name init
# 6. 填充初始数据
npm run db:seed
# 7. 打开数据库管理界面
npm run db:studio
# 8. 执行 SQL 脚本
npm run db:execute -- --file=./scripts/init.sql
# 9. 推送 Schema 到数据库
npm run db:push
# 10. 重置数据库
npm run migrate:reset八、常见问题与解决方案
8.1 db pull 无法识别某些类型
问题:某些 SQL 类型无法正确映射到 Prisma 类型。
解决方案:
prisma
// 手动调整 Schema
model User {
id Int @id @default(autoincrement())
phone BigInt? // 手动调整类型
status String // 枚举类型可能被识别为 String
@@map("users")
}
// 可以定义枚举
enum Status {
ACTIVE
INACTIVE
PENDING
}8.2 seed 脚本报错
问题:执行 npx prisma db seed 报错。
解决方案:
bash
# 检查 seed 配置
cat package.json | grep -A 2 "prisma"
# 手动执行 seed 脚本
node prisma/seed.js
# 检查 Prisma Client 是否生成
npx prisma generate
# 检查数据库连接
npx prisma db pull8.3 db execute 权限不足
问题:执行 SQL 时权限不足。
解决方案:
bash
# 检查数据库用户权限
# 使用有足够权限的用户
# 或者在数据库中授予权限
GRANT ALL PRIVILEGES ON mydb.* TO 'user'@'localhost';
FLUSH PRIVILEGES;8.4 迁移冲突问题
问题:执行迁移时提示冲突。
解决方案:
bash
# 查看迁移状态
npx prisma migrate status
# 标记迁移为已应用
npx prisma migrate resolve --applied "migration_name"
# 重置数据库(注意:会清空数据)
npx prisma migrate reset九、命令速查表
9.1 数据库命令速查
| 命令 | 作用 | 常用参数 |
|---|---|---|
db pull | 从数据库同步 Schema | --schema, --print, --force |
db push | 推送 Schema 到数据库 | --accept-data-loss |
db seed | 填充初始数据 | - |
db execute | 执行 SQL | --file, --stdin, --url |
db drop | 删除数据库 | --force |
db create | 创建数据库 | - |
9.2 迁移命令速查
| 命令 | 作用 | 常用参数 |
|---|---|---|
migrate dev | 开发环境迁移 | --name, --create-only |
migrate deploy | 生产环境部署迁移 | - |
migrate reset | 重置数据库 | --force |
migrate status | 查看迁移状态 | - |
migrate resolve | 解决迁移问题 | --applied, --rolled-back |
十、学习要点总结
10.1 核心概念总结
code
Prisma 数据库命令核心要点:
│
├── db pull
│ ├── 从数据库同步到 Schema
│ ├── 已有数据库初始化项目
│ └── 数据库迁移场景
│
├── db push
│ ├── 从 Schema 同步到数据库
│ ├── 快速原型开发
│ └── 不生成迁移文件
│
├── db seed
│ ├── 填充初始数据
│ ├── 测试数据生成
│ └── 需要在 package.json 配置
│
├── db execute
│ ├── 执行原生 SQL
│ ├── 创建存储过程、视图
│ └── 批量数据操作
│
└── migrate
├── 团队协作推荐
├── 版本控制
└── 生产环境部署10.2 命令选择指南
code
如何选择 Prisma 数据库命令:
│
├── 是否已有数据库?
│ ├── 是 → db pull + migrate dev
│ └── 否 → 直接编辑 Schema
│
├── 是否团队协作?
│ ├── 是 → migrate dev(生成迁移文件)
│ └── 否 → db push(快速迭代)
│
├── 是否需要填充数据?
│ ├── 是 → db seed
│ └── 否 → 跳过
│
└── 是否需要执行 SQL?
├── 是 → db execute
└── 否 → 跳过10.3 学习路径规划
code
学习路径规划:
│
├── 第一阶段:理解概念(1 天)
│ ├── 理解各命令的作用
│ ├── 理解命令执行方向
│ └── 理解使用场景
│
├── 第二阶段:实践操作(2-3 天)
│ ├── 使用 db pull 拉取 Schema
│ ├── 使用 db seed 填充数据
│ ├── 使用 db execute 执行 SQL
│ └── 使用 migrate 管理迁移
│
└── 第三阶段:深入应用(持续)
├── 数据库迁移实践
├── 团队协作流程
└── 性能优化10.4 重要提示
重要提示:
db pull和db push是相反的操作,db pull是从数据库同步到 Schema,db push是从 Schema 同步到数据库。已有数据库时使用db pull,新项目开发时使用db push或migrate dev。生产环境务必使用migrate系列命令,确保迁移可追溯、可回滚!