关系模式
在 Prisma 模式中,记录之间的关系是使用 @relation
属性定义的。例如,在以下架构中,User
和 Post
模型之间存在一对多关系:
¥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:
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 有两种关系模式,foreignKeys
和 prisma
,指定如何强制记录之间的关系。
¥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 DELETE
和 ON 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.
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:
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
设置关系模式的功能是在 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 norelationMode
is explicitly set in thedatasource
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.
如果你在关系模式之间切换,下次你使用 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.
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 theprisma
relation mode. -
‡ PostgreSQL 和 SQLite 的
prisma
关系模式不支持NoAction
引用操作。请改用Restrict
操作。¥‡ The
NoAction
referential action is not supported in theprisma
relation mode for PostgreSQL and SQLite. Instead, use theRestrict
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 会向你触发警告。例如,采用以下模式以及 User
和 Post
模型之间的关系:
¥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:
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 format
或 prisma 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:
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:
在关系模式之间切换
¥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
关系模式,请添加值为 prisma
的 relationMode
字段,或者如果已存在,则将 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.