原型化你的 schema
Prisma CLI 有一个专门用于原型化 schema 的命令: db push
db push
使用与 Prisma Migrate 相同的引擎来同步你的 Prisma schema 和你的数据库 schema。db push
命令
-
内省数据库以推断并执行必要的更改,使你的数据库 schema 反映你的 Prisma schema 的状态。
-
默认情况下,在更改应用到数据库 schema 后,生成器会被触发(例如,Prisma Client)。你不需要手动调用
prisma generate
。 -
如果
db push
预计更改可能导致数据丢失,它将- 抛出一个错误
- 如果你仍然想进行更改,则需要
--accept-data-loss
选项
注意:
选择 db push
或 Prisma Migrate
在以下情况下,db push
工作良好
- 你希望在本地快速原型化和迭代 schema 设计,而无需将这些更改部署到其他环境,例如其他开发者,或暂存和生产环境。
- 你优先考虑达到期望的最终状态,而不是为达到该最终状态而执行的更改或步骤(无法预览
db push
所做的更改) - 你不需要控制 schema 更改如何影响数据。无法编排 schema 和数据迁移——如果
db push
预计更改将导致数据丢失,你可以选择使用--accept-data-loss
选项接受数据丢失,或者停止该过程。无法自定义更改。
请参阅 Schema 原型化与 db push
以了解如何以这种方式使用 db push
的示例。
在以下情况下,不建议使用 db push
- 你希望在不丢失数据的情况下在其他环境中复制你的 schema 更改。你可以使用
db push
进行原型化,但你应该使用迁移来提交 schema 更改并在你的其他环境中应用这些更改。 - 你希望对 schema 更改的执行方式进行细粒度控制 - 例如,重命名列而不是删除并创建一个新的列。
- 你希望跟踪随时间推移对数据库 schema 所做的更改。
db push
不会创建任何允许你跟踪这些更改的工件。 - 你希望 schema 更改是可逆的。你可以再次使用
db push
来恢复到原始状态,但这可能会导致数据丢失。
我可以同时使用 Prisma Migrate 和 db push
吗?
是的,你可以 在你的开发工作流程中一起使用 db push
和 Prisma Migrate 。例如,你可以
- 在项目开始时使用
db push
原型化 schema,并在你对第一个草稿感到满意时初始化迁移历史 - 使用
db push
原型化对现有 schema 的更改,然后运行prisma migrate dev
以从你的更改生成迁移(你将被要求重置)
原型化新的 schema
以下场景演示了如何使用 db push
将新的 schema 与空数据库同步,并演化该 schema - 包括当 db push
检测到更改将导致数据丢失时会发生什么。
-
创建你的 schema 的第一个草稿
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
jobTitle String
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
biograpy String // Intentional typo!
userId Int @unique
user User @relation(fields: [userId], references: [id])
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
posts Post[]
@@unique([name])
} -
使用
db push
将初始 schema 推送到数据库npx prisma db push
-
创建一些示例内容
const add = await prisma.user.create({
data: {
name: 'Eloise',
jobTitle: 'Programmer',
posts: {
create: {
title: 'How to create a MySQL database',
content: 'Some content',
},
},
},
}) -
进行添加性更改 - 例如,创建一个新的必需字段
// ... //
model Post {
id Int @id @default(autoincrement())
title String
description String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
}
// ... // -
推送更改
npx prisma db push
db push
将提示你重置,因为你无法向包含现有内容的表添加必需字段,除非你提供默认值⚠️ We found changes that cannot be executed:
• Added the required column `description` to the `Post` table without a default value. There are 2 rows in this table, it is not possible to execute this.
? To apply this step we need to reset the database, do you want to continue? All data will be lost. » (y/N)
使用 --accept-data-loss
标志来跳过此警告,或 --force-reset
来忽略所有警告。
-
确认数据丢失并将更改应用到你的数据库(或重新审视你的 schema)
There might be data loss when applying the changes:
• Added the required column `description` to the `Post` table without a default value.
? Do you want to ignore the warning(s)? Some data will be lost. » (y/N)注意:与 Prisma Migrate 不同,
db push
不会生成你可以修改以保留数据的迁移,因此最适合在开发环境中进行原型化。 -
继续演化你的 schema,直到它达到相对稳定的状态。
-
初始化迁移历史
npx prisma migrate dev --name initial-state
达到初始原型的步骤不会被保留 -
db push
不会生成历史记录。 -
将你的迁移历史和 Prisma schema 推送到源代码控制系统(例如 Git)。
此时,你的原型化的最终草稿会保存在迁移中,并且可以推送到其他环境(测试、生产或你的团队的其他成员)。
使用现有迁移历史进行原型化
以下场景演示了如何使用 db push
原型化对已存在迁移历史的 Prisma schema 的更改。
-
检出最新的 Prisma schema 和迁移历史
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
jobTitle String
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
biograpy String // Intentional typo!
userId Int @unique
user User @relation(fields: [userId], references: [id])
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
posts Post[]
@@unique([name])
} -
原型化你的新功能,这可能涉及任意数量的步骤。例如,你可能
- 创建
tags String[]
字段,然后运行db push
- 将字段类型更改为
tags Tag[]
并添加一个名为Tag
的新模型,然后运行db push
- 改变主意并恢复原始的
tags String[]
字段,然后调用db push
- 手动更改
tags
字段 - 例如,添加约束
在尝试了几种解决方案后,最终的 schema 更改如下所示
model Post {
id Int @id @default(autoincrement())
title String
description String
published Boolean @default(true)
content String @db.VarChar(500)
authorId Int
author User @relation(fields: [authorId], references: [id])
categories Category[]
tags String[]
} - 创建
-
要创建一个添加新的
tags
字段的迁移,请运行migrate dev
命令npx prisma migrate dev --name added-tags
Prisma Migrate 将提示你重置,因为你手动和使用
db push
在原型化时所做的更改不属于迁移历史√ Drift detected: Your database schema is not in sync with your migration history.
We need to reset the PostgreSQL database "prototyping" at "localhost:5432".
Do you want to continue? All data will be lost. ... yes -
Prisma Migrate 重放现有的迁移历史,基于你的 schema 更改生成新的迁移,并将这些更改应用到数据库。
当使用 migrate dev
时,如果你的 schema 更改意味着 seed 脚本将不再工作,你可以使用 --skip-seed
标志来忽略 seed 脚本。
此时,你的原型化的最终结果会保存在迁移中,并且可以推送到其他环境(测试、生产或你的团队的其他成员)。