跳至主要内容

原型化您的模式

Prisma CLI 有一个专门用于原型化 schema 的命令:db push

db push 使用与 Prisma Migrate 相同的引擎来同步你的 Prisma schema 与你的数据库 schema。db push 命令会

  1. 内省数据库以推断并执行所需的更改,使你的数据库 schema 反映你的 Prisma schema 的状态。

  2. 默认情况下,在更改应用于数据库 schema 后,会触发生成器(例如 Prisma Client)。你无需手动调用 prisma generate

  3. 如果 db push 预计更改可能导致数据丢失,它会

    • 抛出错误
    • 如果你仍然希望进行更改,则需要 --accept-data-loss 选项

备注:

  • db push 不与迁移进行交互或依赖于迁移。迁移表 _prisma_migrations 不会被创建或更新,并且不会生成迁移文件。
  • 在使用 PlanetScale 时,我们建议你使用 db push 而不是 migrate。有关详细信息,请参阅我们的入门文档,根据你的情况选择从头开始指南添加到现有项目指南

选择 db push 还是 Prisma Migrate

db push 在以下情况下效果良好:

  • 你希望在本地快速原型和迭代 schema 设计,而无需将这些更改部署到其他环境,例如其他开发人员、暂存和生产环境。
  • 你优先考虑达到一个期望的最终状态,而不是达到该最终状态所执行的更改或步骤(无法预览 db push 所做的更改)
  • 你不需要控制 schema 更改如何影响数据。无法编排 schema 和数据迁移——如果 db push 预计更改将导致数据丢失,你可以使用 --accept-data-loss 选项接受数据丢失或停止该过程。无法自定义这些更改。

请参阅使用 db push 进行 Schema 原型化以获取如何以这种方式使用 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 检测到更改将导致数据丢失时会发生什么。

  1. 创建 schema 的初稿

    generator client {
    provider = "prisma-client"
    output = "./generated"
    }

    datasource db {
    provider = "postgresql"
    }

    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])
    }
  2. 使用 db push 将初始 schema 推送到数据库

    npx prisma db push
  3. 创建一些示例内容

    const add = await prisma.user.create({
    data: {
    name: 'Eloise',
    jobTitle: 'Programmer',
    posts: {
    create: {
    title: 'How to create a MySQL database',
    content: 'Some content',
    },
    },
    },
    })
  4. 进行添加性更改——例如,创建一个新的必填字段

    // ... //

    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[]
    }

    // ... //
  5. 推送更改

    npx prisma db push

    db push 将失败,因为除非你提供默认值,否则无法向具有现有内容的表添加必填字段。

  6. 重置数据库中的所有数据并重新应用迁移。

    npx prisma migrate reset

    注意:与 Prisma Migrate 不同,db push 不会生成你可以修改以保留数据的迁移,因此最适合在开发环境中进行原型化。

  7. 继续演进你的 schema,直到它达到相对稳定的状态。

  8. 初始化迁移历史记录

    npx prisma migrate dev --name initial-state

    达到初始原型所采取的步骤不会被保留——db push 不会生成历史记录。

  9. 将你的迁移历史记录和 Prisma schema 推送到源代码管理(例如 Git)。

此时,你的原型设计的最终草案已保存在迁移中,可以推送到其他环境(测试、生产或团队的其他成员)。

使用现有迁移历史记录进行原型化

以下场景演示了如何使用 db push 原型化对已存在迁移历史记录的 Prisma schema 的更改。

  1. 检查最新的 Prisma schema 和迁移历史记录

    generator client {
    provider = "prisma-client"
    output = "./generated"
    }

    datasource db {
    provider = "postgresql"
    }

    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])
    }
  2. 原型化你的新功能,这可能涉及任意数量的步骤。例如,你可能

    • 创建一个 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[]
    }
  3. 要创建添加新 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".
    警告

    这将导致数据完全丢失。

    npx prisma migrate reset
  4. Prisma Migrate 会重放现有的迁移历史记录,根据你的 schema 更改生成新的迁移,并将这些更改应用于数据库。

提示

使用 migrate dev 时,如果你的 schema 更改意味着种子脚本将不再起作用,你可以使用 --skip-seed 标志来忽略种子脚本。

此时,你的原型设计的最终结果已保存在迁移中,可以推送到其他环境(测试、生产或团队的其他成员)。

© . This site is unofficial and not affiliated with Prisma Data, Inc.