参考动作升级路径
Prisma ORM 版本 2.x 防止删除某些 Prisma 客户端功能中的连接记录,并且不允许你在 Prisma 模式中配置引用操作来更改该行为。
¥Prisma ORM version 2.x prevents deletion of connected records in some Prisma Client functions, and does not let you configure referential actions in your Prisma Schema to change that behavior.
Prisma ORM 版本 3.x 及更高版本允许你通过在模型关系上显式设置引用操作来控制删除或更新记录时应发生的情况。升级后,Prisma 客户端将不再强制执行任何引用操作,写入数据库外键的任何操作将定义删除或更新记录时的行为。
¥Prisma ORM version 3.x and later lets you control what should happen when deleting or updating records by explicitly setting referential actions on your models' relations. After the upgrade, Prisma Client will not enforce any referential actions anymore, and any action written to the database foreign keys will define the behavior when deleting or updating records.
将外键约束写入数据库时,Prisma Migrate 3.x 将使用 Prisma Client 之前执行的操作作为新的默认操作。
¥Prisma Migrate 3.x will use the actions previously done by Prisma Client as the new default when writing the foreign key constraints to the database.
Prisma ORM 2.x 行为
¥Prisma ORM 2.x behavior
当使用 Prisma 客户端对所需关系调用 delete()
或 deleteAll()
方法时,将执行运行时检查,并防止删除引用相关对象的记录。无论外键如何定义,这都可以防止级联行为。
¥When invoking the delete()
or deleteAll()
methods using Prisma Client on required relations, a runtime check is performed and the deletion of records prevented if they are referencing related objects. This prevents cascade behavior, no matter how the foreign key is defined.
Prisma ORM 2 中的行为在不升级的情况下根本不允许设置引用操作。请参阅 Prisma ORM 2.x 默认参考操作
¥The behavior in Prisma ORM 2, without upgrading, does not allow setting referential actions at all. See Prisma ORM 2.x default referential actions
如果需要实际使用数据库中配置的级联行为,可以使用 raw
SQL 查询到 删除多个引用记录。这是因为 Prisma 客户端不会对原始查询执行运行时检查。
¥If you need to actually use the cascade behavior configured in the database, you can use raw
SQL queries to delete multiple referenced records. This is because Prisma Client will not perform runtime checks on raw queries.
Prisma ORM 2.x 默认引用操作
¥Prisma ORM 2.x default referential actions
以下是使用 Prisma Migrate 版本 2.x 时写入数据库外键的默认引用操作:
¥Below are the default referential actions written to the database foreign keys when using Prisma Migrate versions 2.x:
条款 | 可选关系 | 强制关系 |
---|---|---|
onDelete | SetNull | Cascade |
onUpdate | Cascade | Cascade |
除了数据库引用操作之外,Prisma 客户端版本 2.x 中还强制执行以下操作:
¥On top of the database referential actions, the following actions are enforced in Prisma Client versions 2.x:
条款 | 可选关系 | 强制关系 |
---|---|---|
onDelete | SetNull | Restrict |
onUpdate | Cascade | Cascade |
升级路径
¥Upgrade paths
升级时你可以采取多种路径,根据所需的结果,它们会产生不同的结果。
¥There are a couple of paths you can take when upgrading which will give different results depending on the desired outcome.
如果你当前使用迁移工作流程,则可以运行 prisma db pull
来检查默认值如何反映在你的架构中。如果需要,你可以手动更新数据库。
¥If you currently use the migration workflow, you can run prisma db pull
to check how the defaults are reflected in your schema. You can then manually update your database if you need to.
你还可以决定跳过检查默认值并运行迁移以使用新的默认值更新数据库。
¥You can also decide to skip checking the defaults and run a migration to update your database with the new default values.
使用内省
¥Using Introspection
如果你对数据库进行 内省,则在数据库级别配置的引用操作将反映在你的 Prisma 架构中。如果你一直在使用 Prisma Migrate 或 prisma db push
来管理数据库架构,那么这些很可能是 <=2.25.0 默认值。
¥If you Introspect your database, the referential actions configured at the database level will be reflected in your Prisma Schema. If you have been using Prisma Migrate or prisma db push
to manage the database schema, these are likely to be the <=2.25.0 default values.
当你运行 Introspection 时,Prisma ORM 会将数据库中的所有外键与 schema 进行比较,如果 SQL 语句 ON DELETE
和 ON UPDATE
与默认值不匹配,它们将在 schema 文件中显式设置。
¥When you run an Introspection, Prisma ORM compares all the foreign keys in the database with the schema, if the SQL statements ON DELETE
and ON UPDATE
do not match the default values, they will be explicitly set in the schema file.
内省后,你可以查看架构中的非默认子句。要查看的最重要的子句是 onDelete
,在 2.25.0 及更早版本中默认为 Cascade
。
¥After introspecting, you can review the non-default clauses in your schema. The most important clause to review is onDelete
, which defaults to Cascade
in version 2.25.0 and earlier.
如果你使用 delete()
或 deleteAll()
方法,现在将执行级联删除,因为 Prisma Client 中先前阻止运行时级联删除的安全网已被删除。请务必检查你的代码并进行相应的调整。
¥If you are using either the delete()
or deleteAll()
methods, cascading deletes will now be performed, as the safety net in Prisma Client that previously prevented cascading deletes at runtime is removed. Be sure to check your code and make any adjustments accordingly.
确保你对架构中 onDelete: Cascade
的每种情况都感到满意。如果没有,则:
¥Make sure you are happy with every case of onDelete: Cascade
in your schema. If not, either:
-
修改你的 Prisma 架构和
db push
或dev migrate
以更改数据库或¥Modify your Prisma schema and
db push
ordev migrate
to change the database or -
如果你在工作流程中仅使用
prisma db pull
,请手动更新底层数据库¥Manually update the underlying database if you only use
prisma db pull
in your workflow
以下示例将导致级联删除,这意味着如果删除 User
,则其所有 Post
也将被删除。
¥The following example would result in a cascading delete, meaning that if the User
is deleted then all of their Post
's will be deleted too.
博客架构示例
¥A blog schema example
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId Int
}
model User {
id Int @id @default(autoincrement())
posts Post[]
}
使用迁移
¥Using Migration
运行 迁移(或 prisma db push
命令)时,新的默认值 将应用于你的数据库。
¥When running a Migration (or the prisma db push
command) the new defaults will be applied to your database.
与第一次运行 prisma db pull
时不同,新的引用操作子句和属性不会通过 Prisma VSCode 扩展自动添加到你的 Prisma 架构中。如果你希望使用新默认值以外的任何内容,则必须手动添加它们。
¥Unlike when you run prisma db pull
for the first time, the new referential actions clause and property will not automatically be added to your Prisma schema by the Prisma VSCode extension.
You will have to manually add them if you wish to use anything other than the new defaults.
在 Prisma 架构中显式定义引用操作是可选的。如果你没有显式定义关系的引用操作,Prisma ORM 将使用 新的默认值。
¥Explicitly defining referential actions in your Prisma schema is optional. If you do not explicitly define a referential action for a relation, Prisma ORM uses the new defaults.
请注意,可以根据具体情况添加参考操作。这意味着你可以将它们添加到一个关系中,并通过不手动指定任何内容来将其余设置保留为默认值。
¥Note that referential actions can be added on a case by case basis. This means that you can add them to one single relation and leave the rest set to the defaults by not manually specifying anything.
检查错误
¥Checking for errors
在升级到版本 3.0.1(或启用 referentialActions
功能标志的版本 2.26.0 及更高版本)之前,Prisma ORM 阻止删除记录,同时使用 delete()
或 deleteMany()
来保持引用完整性。Prisma 客户端将抛出自定义运行时错误,错误代码为 P2014
。
¥Before upgrading to version 3.0.1 (or versions 2.26.0 and above with the referentialActions
feature flag enabled), Prisma ORM prevented the deletion of records while using delete()
or deleteMany()
to preserve referential integrity. A custom runtime error would be thrown by Prisma Client with the error code P2014
.
升级后,Prisma ORM 不再执行运行时检查。你可以改为指定自定义引用操作来保留关系之间的引用完整性。
¥After upgrading, Prisma ORM no longer performs runtime checks. You can instead specify a custom referential action to preserve the referential integrity between relations.
当你使用 NoAction
或 Restrict
来防止删除记录时,与之前的版本相比,3.0.1 及更高版本(或启用了 referentialActions
功能标志的 2.26.0)中的错误消息将有所不同。这是因为它们现在由数据库而不是 Prisma 客户端触发。预计新的错误代码是 P2003
,因此你应该检查你的代码以进行相应的调整。
¥When you use NoAction
or Restrict
to prevent the deletion of records, the error messages will be different in versions 3.0.1 and above (or 2.26.0 with the referentialActions
feature flag enabled) compared to versions prior to that. This is because they are now triggered by the database and not Prisma Client. The new error code that can be expected is P2003
, so you should check your code to make adjustments accordingly.
捕获错误的示例
¥Example of catching errors
以下示例使用以下博客架构,Post
和 User
之间具有 1-m 关系,并在 author
字段上设置 Restrict
引用操作。
¥The following example uses the below blog schema with a 1-m relationship between Post
and User
and sets a Restrict
referential actions on the author
field.
这意味着如果用户有帖子,则无法删除该用户(及其帖子)。
¥This means that if a user has a post, that user (and their posts) cannot be deleted.
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id], onDelete: Restrict)
authorId String
}
model User {
id Int @id @default(autoincrement())
posts Post[]
}
升级之前,当你尝试删除有帖子的用户时,你会收到的错误代码为 P2014
,其消息为:
¥Prior to upgrading, the error code you would receive when trying to delete a user which has posts would be P2014
and it's message:
"你尝试进行的更改将违反 {model_a_name} 和 {model_b_name} 模型之间所需的关系 '---左括号---relation_name}'。"
¥"The change you are trying to make would violate the required relation '{relation_name}' between the {model_a_name} and {model_b_name} models."
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
try {
await prisma.user.delete({
where: {
id: 'some-long-id',
},
})
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2014') {
console.log(error.message)
}
}
}
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
为了确保检查代码中的错误是否正确,请修改检查以查找 P2003
,这将传递消息:
¥To make sure you are checking for the correct errors in your code, modify your check to look for P2003
, which will deliver the message:
“该字段的外键约束失败:---左括号---field_name}"
¥"Foreign key constraint failed on the field: {field_name}"
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
try {
await prisma.user.delete({
where: {
id: 'some-long-id'
}
})
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2014') {
if (error.code === 'P2003') {
console.log(error.message)
}
}
}
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})