Skip to main content

关系模式

在 Prisma 模式中,记录之间的关系是使用 @relation 属性定义的。例如,在以下架构中,UserPost 模型之间存在一对多关系:

¥In Prisma schema, relations between records are defined with the @relation attribute. For example, in the following schema there is a one-to-many relation between the User and Post models:

schema.prisma
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)
authorId Int
}

model User {
id Int @id @default(autoincrement())
posts Post[]
}

Prisma ORM 有两种关系模式,foreignKeysprisma,指定如何强制记录之间的关系。

¥Prisma ORM has two relation modes, foreignKeys and prisma, that specify how relations between records are enforced.

如果你将 Prisma ORM 与关系数据库结合使用,则默认情况下 Prisma ORM 使用 foreignKeys 关系模式,它使用外键在数据库级别强制记录之间的关系。外键是一个表中的一列或一组列,它们根据另一个表中的主键获取值。外键允许你:

¥If you use Prisma ORM with a relational database, then by default Prisma ORM uses the foreignKeys relation mode, which enforces relations between records at the database level with foreign keys. A foreign key is a column or group of columns in one table that take values based on the primary key in another table. Foreign keys allow you to:

  • 设置约束以防止你进行破坏引用的更改

    ¥set constraints that prevent you from making changes that break references

  • 设置 参考行动 定义如何处理记录更改

    ¥set referential actions that define how changes to records are handled

这些约束和引用操作共同保证了数据的引用完整性。

¥Together these constraints and referential actions guarantee the referential integrity of the data.

对于上面的示例架构,如果你使用 PostgreSQL 连接器,Prisma Migrate 将默认生成以下 SQL:

¥For the example schema above, Prisma Migrate will generate the following SQL by default if you use the PostgreSQL connector:


-- CreateTable
CREATE TABLE "Post" (
"id" SERIAL NOT NULL,
"title" TEXT NOT NULL,
"authorId" INTEGER NOT NULL,

CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,

CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- AddForeignKey
//highlight-start
ALTER TABLE "Post"
ADD CONSTRAINT "Post_authorId_fkey"
FOREIGN KEY ("authorId")
REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
//highlight-end

在这种情况下,Post 表的 authorId 列上的外键约束引用 User 表的 id 列,并保证帖子必须有存在的作者。如果你更新或删除用户,则 ON DELETEON UPDATE 参考操作会指定 CASCADE 选项,这也将删除或更新属于该用户的所有帖子。

¥In this case, the foreign key constraint on the authorId column of the Post table references the id column of the User table, and guarantees that a post must have an author that exists. If you update or delete a user then the ON DELETE and ON UPDATE referential actions specify the CASCADE option, which will also delete or update all posts belonging to the user.

某些数据库,例如 MongoDB 或 PlanetScale,不支持外键。此外,在某些情况下,开发者可能不愿意在通常支持外键的关系数据库中使用外键。对于这些情况,Prisma ORM 提供了 prisma 关系模式,它模拟关系数据库中关系的一些属性。当你使用启用了 prisma 关系模式的 Prisma 客户端时,查询的行为是相同或相似的,但引用操作和一些约束由 Prisma 引擎而不是在数据库中处理。

¥Some databases, such as MongoDB or PlanetScale, do not support foreign keys. Additionally, in some cases developers may prefer not to use foreign keys in their relational database that usually does support foreign keys. For these situations, Prisma ORM offers the prisma relation mode, which emulates some properties of relations in relational databases. When you use Prisma Client with the prisma relation mode enabled, the behavior of queries is identical or similar, but referential actions and some constraints are handled by the Prisma engine rather than in the database.

warning

Prisma 客户端中引用完整性和引用操作的模拟会对性能产生影响。在底层数据库支持外键的情况下,它通常是首选。

¥There are performance implications to emulation of referential integrity and referential actions in Prisma Client. In cases where the underlying database supports foreign keys, it is usually the preferred choice.

如何在 Prisma 架构中设置关系模式

¥How to set the relation mode in your Prisma schema

要设置关系模式,请在 datasource 块中添加 relationMode 字段:

¥To set the relation mode, add the relationMode field in the datasource block:

schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
info

设置关系模式的功能是在 Prisma ORM 版本 3.1.1 中作为 referentialIntegrity 预览功能的一部分引入的,并且在 Prisma ORM 版本 4.8.0 及更高版本中普遍可用。

relationMode 字段在 Prisma ORM 版本 4.5.0 中被重命名 ,之前被命名为 referentialIntegrity

¥The ability to set the relation mode was introduced as part of the referentialIntegrity preview feature in Prisma ORM version 3.1.1, and is generally available in Prisma ORM versions 4.8.0 and later.

The relationMode field was renamed in Prisma ORM version 4.5.0, and was previously named referentialIntegrity.

对于关系数据库,可用的选项有:

¥For relational databases, the available options are:

  • foreignKeys:这使用外键处理数据库中的关系。这是所有关系数据库连接器的默认选项,如果 datasource 块中没有显式设置 relationMode,则该选项处于活动状态。

    ¥foreignKeys: this handles relations in the database with foreign keys. This is the default option for all relational database connectors and is active if no relationMode is explicitly set in the datasource block.

  • prisma:这模拟了 Prisma 客户端中的关系。当你将 MySQL 连接器与 PlanetScale 数据库一起使用并且未在 PlanetScale 数据库设置中启用原生外键约束时,你还应该 启用此选项

    ¥prisma: this emulates relations in Prisma Client. You should also enable this option when you use the MySQL connector with a PlanetScale database and don't have native foreign key constraints enabled in your PlanetScale database settings.

对于 MongoDB,唯一可用的选项是 prisma 关系模式。如果 datasource 块中没有显式设置 relationMode,则该模式也处于活动状态。

¥For MongoDB, the only available option is the prisma relation mode. This mode is also active if no relationMode is explicitly set in the datasource block.

warning

如果你在关系模式之间切换,下次你使用 Prisma Migrate 或 db push 对架构应用更改时,Prisma ORM 将向你的数据库添加或删除外键。请参阅 在关系模式之间切换 了解更多信息。

¥If you switch between relation modes, Prisma ORM will add or remove foreign keys to your database next time you apply changes to your schema with Prisma Migrate or db push. See Switch between relation modes for more information.

使用 foreignKeys 关系模式处理关系数据库中的关系

¥Handle relations in your relational database with the foreignKeys relation mode

foreignKeys 关系模式使用外键处理关系数据库中的关系。当你使用关系数据库连接器(PostgreSQL、MySQL、SQLite、SQL Server、CockroachDB)时,这是默认选项。

¥The foreignKeys relation mode handles relations in your relational database with foreign keys. This is the default option when you use a relational database connector (PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB).

使用 MongoDB 连接器时,foreignKeys 关系模式不可用。一些关系数据库,例如 PlanetScale,也禁止使用外键。在这些情况下,你应该改为 使用 prisma 关系模式模拟 Prisma ORM 中的关系

¥The foreignKeys relation mode is not available when you use the MongoDB connector. Some relational databases, such as PlanetScale, also forbid the use of foreign keys. In these cases, you should instead emulate relations in Prisma ORM with the prisma relation mode.

参照完整性

¥Referential integrity

foreignKeys 关系模式通过外键约束和引用操作在数据库级别维护引用完整性。

¥The foreignKeys relation mode maintains referential integrity at the database level with foreign key constraints and referential actions.

外键约束

¥Foreign key constraints

当你创建或更新与另一条记录有关系的记录时,相关记录需要存在。外键约束在数据库中强制执行此行为。如果该记录不存在,数据库将返回错误信息。

¥When you create or update a record with a relation to another record, the related record needs to exist. Foreign key constraints enforce this behavior in the database. If the record does not exist, the database will return an error message.

参考行动

¥Referential actions

当你更新或删除与另一条记录有关系的记录时,会在数据库中触发引用操作。为了维护相关记录中的引用完整性,引用操作可以防止会破坏引用完整性的更改、将更改级联到相关记录,或者将引用已更新或已删除记录的字段值设置为 null 或默认值。

¥When you update or delete a record with a relation to another record, referential actions are triggered in the database. To maintain referential integrity in related records, referential actions prevent changes that would break referential integrity, cascade changes through to related records, or set the value of fields that reference the updated or deleted records to a null or default value.

有关详细信息,请参阅 参考行动 页。

¥For more information, see the referential actions page.

内省

¥Introspection

当你在启用了 foreignKeys 关系模式的情况下使用 db pull 命令内省关系数据库时,@relation 属性将添加到存在外键的关系的 Prisma 架构中。

¥When you introspect a relational database with the db pull command with the foreignKeys relation mode enabled, a @relation attribute will be added to your Prisma schema for relations where foreign keys exist.

Prisma Migrate 和 db push

¥Prisma Migrate and db push

当你使用启用了 foreignKeys 关系模式的 Prisma Migrate 或 db push 对 Prisma 架构应用更改时,将在数据库中为架构中的所有 @relation 属性创建外键。

¥When you apply changes to your Prisma schema with Prisma Migrate or db push with the foreignKeys relation mode enabled, foreign keys will be created in your database for all @relation attributes in your schema.

使用 prisma 关系模式模拟 Prisma ORM 中的关系

¥Emulate relations in Prisma ORM with the prisma relation mode

prisma 关系模式使用一些额外的数据库查询和逻辑,为每个 Prisma 客户端查询模拟一些外键约束和引用操作,以维护引用完整性。

¥The prisma relation mode emulates some foreign key constraints and referential actions for each Prisma Client query to maintain referential integrity, using some additional database queries and logic.

prisma 关系模式是 MongoDB 连接器的默认选项。如果你使用不支持外键的关系数据库,也应该设置它。例如,如果你使用 PlanetScale 没有外键约束,则应使用 prisma 关系模式。

¥The prisma relation mode is the default option for the MongoDB connector. It should also be set if you use a relational database that does not support foreign keys. For example, if you use PlanetScale without foreign key constraints, you should use the prisma relation mode.

warning

Prisma Client 中引用完整性的模拟会对性能产生影响,因为它使用额外的数据库查询来维护引用完整性。在底层数据库可以使用外键处理引用完整性的情况下,它通常是首选。

¥There are performance implications to emulation of referential integrity in Prisma Client, because it uses additional database queries to maintain referential integrity. In cases where the underlying database can handle referential integrity with foreign keys, it is usually the preferred choice.

关系模拟仅适用于 Prisma 客户端查询,不适用于原始查询。

¥Emulation of relations is only available for Prisma Client queries and does not apply to raw queries.

模拟哪些外键约束?

¥Which foreign key constraints are emulated?

当你更新记录时,Prisma ORM 将模拟外键约束。这意味着当你更新与另一条记录相关的记录时,相关记录需要存在。如果记录不存在,Prisma Client 将返回错误消息。

¥When you update a record, Prisma ORM will emulate foreign key constraints. This means that when you update a record with a relation to another record, the related record needs to exist. If the record does not exist, Prisma Client will return an error message.

但是,当你创建记录时,Prisma ORM 不会模拟任何外键约束。你将能够创建无效数据。

¥However, when you create a record, Prisma ORM does not emulate any foreign key constraints. You will be able to create invalid data.

模拟哪些参考动作?

¥Which referential actions are emulated?

当你更新或删除具有相关记录的记录时,Prisma ORM 将模拟引用操作。

¥When you update or delete a record with related records, Prisma ORM will emulate referential actions.

下表显示了每个数据库连接器可用的模拟引用操作:

¥The following table shows which emulated referential actions are available for each database connector:

数据库级联限制无动作置空默认设置
PostgreSQL**✔️ ****✔️ ****✔️ **
MySQL**✔️ ****✔️ ****✔️ ****✔️ **
SQLite**✔️ ****✔️ ****✔️ **
SQL Server**✔️ ****✔️ ****✔️ ****✔️ **
CockroachDB**✔️ ****✔️ ****✔️ ****✔️ **
MongoDB**✔️ ****✔️ ****✔️ ****✔️ **
  • prisma 关系模式不支持 SetDefault 参考操作。

    ¥† The SetDefault referential action is not supported in the prisma relation mode.

  • ‡ PostgreSQL 和 SQLite 的 prisma 关系模式不支持 NoAction 引用操作。请改用 Restrict 操作。

    ¥‡ The NoAction referential action is not supported in the prisma relation mode for PostgreSQL and SQLite. Instead, use the Restrict action.

错误信息

¥Error messages

prisma 关系模式下的模拟约束和引用操作返回的错误消息由 Prisma Client 生成,与 foreignKeys 关系模式下的错误消息略有不同:

¥Error messages returned by emulated constraints and referential actions in the prisma relation mode are generated by Prisma Client and differ slightly from the error messages in the foreignKeys relation mode:

Example:
// foreignKeys:
... Foreign key constraint failed on the field: `ProfileOneToOne_userId_fkey (index)`
// prisma:
... The change you are trying to make would violate the required relation 'ProfileOneToOneToUserOneToOne' between the `ProfileOneToOne` and `UserOneToOne` models.

内省

¥Introspection

当你在启用了 prisma 关系模式的情况下使用 db pull 命令内省数据库时,关系不会自动添加到你的架构中。你将需要使用 @relation 属性手动添加任何关系。这只需要完成一次 - 下次你检查数据库时,Prisma ORM 将保留你添加的 @relation 属性。

¥When you introspect a database with the db pull command with the prisma relation mode enabled, relations will not be automatically added to your schema. You will instead need to add any relations manually with the @relation attribute. This only needs to be done once – next time you introspect your database, Prisma ORM will keep your added @relation attributes.

Prisma Migrate 和 db push

¥Prisma Migrate and db push

当你使用启用了 prisma 关系模式的 Prisma Migrate 或 db push 对 Prisma 架构应用更改时,Prisma ORM 将不会在数据库中使用外键。

¥When you apply changes to your Prisma schema with Prisma Migrate or db push with the prisma relation mode enabled, Prisma ORM will not use foreign keys in your database.

索引

¥Indexes

在使用外键约束的关系数据库中,数据库通常还会隐式地为外键列创建索引。例如,MySQL 将在所有外键列上创建索引。这是为了允许外键检查快速运行并且不需要表扫描。

¥In relational databases that use foreign key constraints, the database usually also implicitly creates an index for the foreign key columns. For example, MySQL will create an index on all foreign key columns. This is to allow foreign key checks to run fast and not require a table scan.

prisma 关系模式不使用外键,因此当你使用 Prisma Migrate 或 db push 将更改应用到数据库时,不会创建任何索引。相反,你需要使用 @@index 属性(或 @unique@@unique@@id 属性,如果适用)在关系标量字段上手动添加索引。

¥The prisma relation mode does not use foreign keys, so no indexes are created when you use Prisma Migrate or db push to apply changes to your database. You instead need to manually add an index on your relation scalar fields with the @@index attribute (or the @unique, @@unique or @@id attributes, if applicable).

索引验证

¥Index validation

如果不手动添加索引,查询可能需要全表扫描。这可能会很慢,而且对于按访问行计费的数据库提供商来说也很昂贵。为了帮助避免这种情况,当你的架构包含在未定义索引的 @relation 中使用的字段时,Prisma ORM 会向你触发警告。例如,采用以下模式以及 UserPost 模型之间的关系:

¥If you do not add the index manually, queries might require full table scans. This can be slow, and also expensive on database providers that bill per accessed row. To help avoid this, Prisma ORM warns you when your schema contains fields that are used in a @relation that does not have an index defined. For example, take the following schema with a relation between the User and Post models:

schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}

model User {
id Int @id
posts Post[]
}

model Post {
id Int @id
userId Int
user User @relation(fields: [userId], references: [id])
}

当你运行 prisma formatprisma validate 时,Prisma ORM 显示以下警告:

¥Prisma ORM displays the following warning when you run prisma format or prisma validate:

With `relationMode = "prisma"`, no foreign keys are used, so relation fields will not benefit from the index usually created by the relational database under the hood. This can lead to poor performance when querying these fields. We recommend adding an index manually.

要解决此问题,请向 Post 模型添加索引:

¥To fix this, add an index to your Post model:

schema.prisma
model Post {
id Int @id
userId Int
user User @relation(fields: [userId], references: [id])

@@index([userId])
}

如果你使用 Prisma VS Code 扩展(或我们的 另一个编辑器中的语言服务器),警告会通过快速修复来增强,该修复会为你添加所需的索引:

¥If you use the Prisma VS Code extension (or our language server in another editor), the warning is augmented with a Quick Fix that adds the required index for you:

The Quick Fix pop-up for adding an index on a relation scalar field in VS Code

在关系模式之间切换

¥Switch between relation modes

仅当你使用关系数据库连接器(PostgreSQL、MySQL、SQLite、SQL Server、CockroachDB)时,才可以在关系模式之间切换。

¥It is only possible to switch between relation modes when you use a relational database connector (PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB).

foreignKeys 切换到 prisma

¥Switch from foreignKeys to prisma

如果你使用关系数据库并且 datasource 块中不包含 relationMode 字段,则默认关系模式为 foreignKeys。要切换到 prisma 关系模式,请添加值为 prismarelationMode 字段,或者如果已存在,则将 relationMode 字段值更新为 prisma

¥The default relation mode if you use a relational database and do not include the relationMode field in your datasource block is foreignKeys. To switch to the prisma relation mode, add the relationMode field with a value of prisma, or update the relationMode field value to prisma if it already exists.

当你将关系模式从 foreignKeys 切换到 prisma 时,在你首次使用 Prisma Migrate 或 db push 对架构应用更改后,Prisma ORM 将在下次迁移中删除所有先前创建的外键。

¥When you switch the relation mode from foreignKeys to prisma, after you first apply changes to your schema with Prisma Migrate or db push Prisma ORM will remove all previously created foreign keys in the next migration.

如果保留相同的数据库,则可以继续正常工作。如果你切换到根本不支持外键的数据库,则现有迁移历史记录包含创建外键的 SQL DDL,如果你必须重新运行这些迁移,则可能会触发错误。在这种情况下,我们建议你删除 migrations 目录。(如果你使用不支持外键的 PlanetScale,我们一般建议你使用 使用 db push 而不是 Prisma Migrate。)

¥If you keep the same database, you can then continue to work as normal. If you switch to a database that does not support foreign keys at all, your existing migration history contains SQL DDL that creates foreign keys, which might trigger errors if you ever have to rerun these migrations. In this case, we recommend that you delete the migrations directory. (If you use PlanetScale, which does not support foreign keys, we generally recommend that you use db push rather than Prisma Migrate.)

prisma 切换到 foreignKeys

¥Switch from prisma to foreignKeys

如需从 prisma 关系模式切换到 foreignKeys 关系模式,请将 relationMode 字段值从 prisma 更新为 foreignKeys。为此,数据库必须支持外键。当你在切换关系模式后首次使用 Prisma Migrate 或 db push 对架构应用更改时,Prisma ORM 将为下一次迁移中的所有关系创建外键。

¥To switch from the prisma relation mode to the foreignKeys relation mode, update the relationMode field value from prisma to foreignKeys. To do this, the database must support foreign keys. When you apply changes to your schema with Prisma Migrate or db push for the first time after you switch relation modes, Prisma ORM will create foreign keys for all relations in the next migration.