原型化您的 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 和資料 migration — 如果
db push
預期變更將導致資料遺失,您可以接受使用--accept-data-loss
選項遺失資料,或停止該程序。 無法自訂變更。
請參閱使用 db push
進行 Schema 原型化,以取得如何以這種方式使用 db push
的範例。
在以下情況下,不建議使用 db push
- 您想要在不遺失資料的情況下,在其他環境中複製您的 schema 變更。 您可以使用
db push
進行原型化,但您應該使用 migration 來提交 schema 變更,並在您的其他環境中套用這些變更。 - 您想要精細控制 schema 變更的執行方式 - 例如,重新命名欄位而不是刪除它並建立一個新欄位。
- 您想要追蹤一段時間內對資料庫 schema 所做的變更。
db push
不會建立任何構件,讓您可以追蹤這些變更。 - 您希望 schema 變更是可逆的。您可以再次使用
db push
還原到原始狀態,但這可能會導致資料遺失。
我可以同時使用 Prisma Migrate 和 db push
嗎?
是的,您可以在您的開發工作流程中一起使用 db push
和 Prisma Migrate。 例如,您可以
- 在專案開始時使用
db push
原型化 schema,並在您對第一個草稿感到滿意時初始化 migration 歷史記錄 - 使用
db push
原型化對現有 schema 的變更,然後執行prisma migrate dev
從您的變更產生 migration (系統會要求您重置)
原型化新的 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
不會產生您可以修改以保留資料的 migration,因此最適合在開發環境中進行原型化。 -
繼續演進您的 schema,直到它達到相對穩定的狀態。
-
初始化 migration 歷史記錄
npx prisma migrate dev --name initial-state
達到初始原型的步驟未被保留 -
db push
不會產生歷史記錄。 -
將您的 migration 歷史記錄和 Prisma schema 推送到原始碼控制 (例如 Git)。
此時,您的原型化的最終草稿會保留在 migration 中,並且可以推送到其他環境 (測試、生產環境或您團隊的其他成員)。
使用現有 migration 歷史記錄進行原型化
以下情境示範如何使用 db push
原型化對 Prisma schema 的變更,其中已存在 migration 歷史記錄。
-
檢查最新的 Prisma schema 和 migration 歷史記錄
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
欄位的 migration,請執行migrate dev
指令npx prisma migrate dev --name added-tags
Prisma Migrate 會提示您重置,因為您在原型化時手動和使用
db push
所做的變更不屬於 migration 歷史記錄的一部分√ 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 會重播現有的 migration 歷史記錄,根據您的 schema 變更產生新的 migration,並將這些變更套用至資料庫。
當使用 migrate dev
時,如果您的 schema 變更表示種子指令碼將不再運作,您可以使用 --skip-seed
標記來忽略種子指令碼。
此時,您的原型化的最終結果會保留在 migration 中,並且可以推送到其他環境 (測試、生產環境或您團隊的其他成員)。