原型化你的 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
选项接受数据丢失,或停止该过程。没有办法自定义更改。
有关如何以这种方式使用 db push
的示例,请参阅 使用 db push
进行 Schema 原型化。
如果以下情况,不推荐使用 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 更改意味着种子脚本将不再起作用,你可以使用 --skip-seed
标志来忽略种子脚本。
此时,你的原型化的最终结果将保存在迁移中,并且可以推送到其他环境(测试、生产或你的团队的其他成员)。