一对一的关系
本页介绍一对一关系并解释如何在 Prisma 模式中使用它们。
¥This page introduces one-to-one relations and explains how to use them in your Prisma schema.
概述
¥Overview
一对一(1-1)关系是指关系两侧最多可以连接一条记录的关系。在下面的示例中,User
和 Profile
之间存在一对一的关系:
¥One-to-one (1-1) relations refer to relations where at most one record can be connected on both sides of the relation. In the example below, there is a one-to-one relation between User
and Profile
:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id])
userId Int @unique // relation scalar field (used in the `@relation` attribute above)
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
profile Profile?
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
user User @relation(fields: [userId], references: [id])
userId String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
}
userId
关系标量是底层数据库中外键的直接表示。这种一对一的关系表达如下:
¥The userId
relation scalar is a direct representation of the foreign key in the underlying database. This one-to-one relation expresses the following:
-
"一名用户可以有零个配置文件或一个配置文件"(因为
profile
字段是User
上的 optional)¥"a user can have zero profiles or one profile" (because the
profile
field is optional onUser
) -
"一个配置文件必须始终连接到一个用户"
¥"a profile must always be connected to one user"
在前面的示例中,Profile
模型的 user
关系字段引用了 User
模型的 id
字段。你还可以引用不同的字段。在这种情况下,你需要使用 @unique
属性来标记该字段,以保证每个 Profile
上只有一个 User
连接。在以下示例中,user
字段引用 User
模型中的 email
字段,该字段用 @unique
属性标记:
¥In the previous example, the user
relation field of the Profile
model references the id
field of the User
model. You can also reference a different field. In this case, you need to mark the field with the @unique
attribute, to guarantee that there is only a single User
connected to each Profile
. In the following example, the user
field references an email
field in the User
model, which is marked with the @unique
attribute:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
email String @unique // <-- add unique attribute
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userEmail], references: [email])
userEmail String @unique // relation scalar field (used in the `@relation` attribute above)
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique // <-- add unique attribute
profile Profile?
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
user User @relation(fields: [userEmail], references: [email])
userEmail String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
}
在 MySQL 中,你可以创建仅在引用端有索引且没有唯一约束的外键。在 Prisma ORM 版本 4.0.0 及更高版本中,如果你内省这种类型的关系,它将触发验证错误。要解决此问题,你需要向引用的字段添加 @unique
约束。
¥In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma ORM versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a @unique
constraint to the referenced field.
关系数据库中的多字段关系
¥Multi-field relations in relational databases
仅在关系数据库中,你还可以使用 多字段 ID 定义 1-1 关系:
¥In relational databases only, you can also use multi-field IDs to define a 1-1 relation:
model User {
firstName String
lastName String
profile Profile?
@@id([firstName, lastName])
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userFirstName, userLastName], references: [firstName, lastName])
userFirstName String // relation scalar field (used in the `@relation` attribute above)
userLastName String // relation scalar field (used in the `@relation` attribute above)
@@unique([userFirstName, userLastName])
}
数据库中的 1-1 关系
¥1-1 relations in the database
关系数据库
¥Relational databases
以下示例演示如何在 SQL 中创建 1-1 关系:
¥The following example demonstrates how to create a 1-1 relation in SQL:
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Profile" (
id SERIAL PRIMARY KEY,
"userId" INTEGER NOT NULL UNIQUE,
FOREIGN KEY ("userId") REFERENCES "User"(id)
);
请注意,外键 userId
存在 UNIQUE
约束。如果缺少此 UNIQUE
约束,则该关系将被视为 1-n 关系。
¥Notice that there is a UNIQUE
constraint on the foreign key userId
. If this UNIQUE
constraint was missing, the relation would be considered a 1-n relation.
以下示例演示如何使用组合键(firstName
和 lastName
)在 SQL 中创建 1-1 关系:
¥The following example demonstrates how to create a 1-1 relation in SQL using a composite key (firstName
and lastName
):
CREATE TABLE "User" (
firstName TEXT,
lastName TEXT,
PRIMARY KEY ("firstName","lastName")
);
CREATE TABLE "Profile" (
id SERIAL PRIMARY KEY,
"userFirstName" TEXT NOT NULL,
"userLastName" TEXT NOT NULL,
UNIQUE ("userFirstName", "userLastName")
FOREIGN KEY ("userFirstName", "userLastName") REFERENCES "User"("firstName", "lastName")
);
MongoDB
对于 MongoDB,Prisma ORM 目前使用 规范化数据模型设计,这意味着文档以与关系数据库类似的方式通过 ID 相互引用。
¥For MongoDB, Prisma ORM currently uses a normalized data model design, which means that documents reference each other by ID in a similar way to relational databases.
以下 MongoDB 文档代表 User
:
¥The following MongoDB document represents a User
:
{ "_id": { "$oid": "60d58e130011041800d209e1" }, "name": "Bob" }
以下 MongoDB 文档代表 Profile
- 注意 userId
字段,它引用 User
文档的 $oid
:
¥The following MongoDB document represents a Profile
- notice the userId
field, which references the User
document's $oid
:
{
"_id": { "$oid": "60d58e140011041800d209e2" },
"bio": "I'm Bob, and I like drawing.",
"userId": { "$oid": "60d58e130011041800d209e1" }
}
必填和可选 1-1 关系字段
¥Required and optional 1-1 relation fields
在一对一关系中,没有关系标量的关系一侧(表示数据库中外键的字段)必须是可选的:
¥In a one-to-one relation, the side of the relation without a relation scalar (the field representing the foreign key in the database) must be optional:
model User {
id Int @id @default(autoincrement())
profile Profile? // No relation scalar - must be optional
}
此限制是在 2.12.0 中引入的。
¥This restriction was introduced in 2.12.0.
但是,你可以选择带有关系标量的关系的一侧是可选的还是强制的。
¥However, you can choose if the side of the relation with a relation scalar should be optional or mandatory.
强制 1-1 关系
¥Mandatory 1-1 relation
在以下示例中,profile
和 profileId
为必填项。这意味着你无法在不连接或创建 Profile
的情况下创建 User
:
¥In the following example, profile
and profileId
are mandatory. This means that you cannot create a User
without connecting or creating a Profile
:
model User {
id Int @id @default(autoincrement())
profile Profile @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
profileId Int @unique // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
可选的 1-1 关系
¥Optional 1-1 relation
在以下示例中,profile
和 profileId
是可选的。这意味着你可以创建用户而无需连接或创建 Profile
:
¥In the following example, profile
and profileId
are optional. This means that you can create a user without connecting or creating a Profile
:
model User {
id Int @id @default(autoincrement())
profile Profile? @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
profileId Int? @unique // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
选择哪一方应以 1-1 关系存储外键
¥Choosing which side should store the foreign key in a 1-1 relation
在 1-1 关系中,你可以自己决定要使用 @relation
属性注释关系的哪一侧(因此保留外键)。
¥In 1-1 relations, you can decide yourself which side of the relation you want to annotate with the @relation
attribute (and therefore holds the foreign key).
在以下示例中,Profile
模型上的关系字段使用 @relation
属性进行注释。userId
是底层数据库中外键的直接表示:
¥In the following example, the relation field on the Profile
model is annotated with the @relation
attribute. userId
is a direct representation of the foreign key in the underlying database:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id])
userId Int @unique // relation scalar field (used in the `@relation` attribute above)
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
profile Profile?
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
user User @relation(fields: [userId], references: [id])
userId String @unique @db.ObjectId
}
你还可以使用 @relation
属性注释关系的另一端。以下示例注释了 User
模型上的关系字段。profileId
是底层数据库中外键的直接表示:
¥You can also annotate the other side of the relation with the @relation
attribute. The following example annotates the relation field on the User
model. profileId
is a direct representation of the foreign key in the underlying database:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
profile Profile? @relation(fields: [profileId], references: [id])
profileId Int? @unique // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
profile Profile? @relation(fields: [profileId], references: [id])
profileId String? @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
user User?
}