跳至主要内容

原型设计您的模式

Prisma CLI 拥有一个专门用于原型设计模式的命令:db push

db push 使用与 Prisma Migrate 相同的引擎来同步您的 Prisma 模式与数据库模式。db push 命令

  1. 自省数据库以推断并执行使您的数据库模式反映 Prisma 模式状态所需的更改。

  2. 默认情况下,在将更改应用于数据库模式后,将触发生成器(例如 Prisma 客户端)。您不需要手动调用 prisma generate

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

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

注意:

  • db push 不与迁移交互或依赖于迁移。迁移表 _prisma_migrations 不会创建或更新,也不会生成任何迁移文件。
  • 在使用 PlanetScale 时,我们建议您使用 db push 而不是 migrate。有关详细信息,请参阅我们的入门文档,具体取决于您的情况,请参阅 从头开始添加到现有项目

选择 db push 或 Prisma Migrate

db push 在以下情况下很有效

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

请参阅 使用 db push 进行模式原型设计,了解如何以这种方式使用 db push 的示例。

在以下情况下,不建议使用 db push 

  • 您希望在其他环境中复制模式更改,而不会丢失数据。您可以使用 db push 进行原型设计,但应使用迁移提交模式更改并在其他环境中应用这些更改。
  • 您希望对模式更改的执行方式进行细粒度控制 - 例如,重命名列而不是删除它并创建一个新的列
  • 您希望跟踪对数据库模式所做的更改。 db push 不会创建任何允许您跟踪这些更改的工件。
  • 您希望模式更改可逆。您可以再次使用 db push 恢复到原始状态,但这可能会导致数据丢失。

我可以将 Prisma Migrate 和 db push 结合使用吗?

是的,您可以在开发工作流中将 db push 和 Prisma Migrate 结合使用。例如,您可以

  • 使用 db push 为项目开始时原型设计模式,并在对第一个草稿感到满意时初始化迁移历史记录。
  • 使用 db push 为现有模式原型设计更改,然后运行 prisma migrate dev 从更改中生成迁移(系统会要求您重置)。

原型设计新模式

以下场景演示了如何使用 db push 将新模式与空数据库同步,并发展该模式 - 包括 db push 检测到更改会导致数据丢失时会发生什么。

  1. 创建模式的第一个草稿。

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

    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 会提示您重置,因为您无法在没有提供默认值的情况下向包含现有内容的表中添加必填字段。

    ⚠️ 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 忽略所有警告。

  1. 确认数据丢失并将更改应用于您的数据库(或重新访问您的模式)。

     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 不会生成您可以修改以保留数据的迁移,因此最适合在开发环境中进行原型设计。

  2. 继续发展您的模式,直到它达到相对稳定的状态。

  3. 初始化迁移历史记录。

    npx prisma migrate dev --name initial-state

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

  4. 将您的迁移历史记录和 Prisma 模式推送到源代码控制(例如 Git)。

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

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

以下场景演示了如何使用 db push 为 Prisma 模式原型设计更改,其中已存在迁移历史记录。

  1. 签出最新的 Prisma 模式和迁移历史记录。

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

    • 创建 tags String[] 字段,然后运行 db push
    • 将字段类型更改为 tags Tag[] 并添加名为 Tag 的新模型,然后运行 db push
    • 改变主意并恢复原始 tags String[] 字段,然后调用 db push
    • 对数据库中的 tags 字段进行手动更改 - 例如,添加约束。

    在尝试了几种解决方案后,最终的模式更改如下所示。

    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".
    Do you want to continue? All data will be lost. ... yes
  4. Prisma Migrate 重新播放现有的迁移历史记录,根据您的模式更改生成新的迁移,并将这些更改应用于数据库。

提示

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

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