跳至主要内容

一对一关系

快速摘要

了解如何在 Prisma 模式中定义和使用一对一(1-1)关系,包括建模选择和关键概念。

本页介绍了一对一关系,并解释了如何在 Prisma 模式中使用它们。

本页面回答的问题
  • 我如何建模一对一关系?
  • 哪一方应该存储外键?
  • 可选与必需的 1-1 关系如何运作?

概述

一对一(1-1)关系是指关系的两端至多只能连接**一条**记录。在下面的示例中,`User` 和 `Profile` 之间存在一对一关系。

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)
}

`userId` 关系标量是底层数据库中外键的直接表示。这种一对一关系表达了以下内容:

  • "一个用户可以拥有零个或一个个人资料"(因为 `User` 上的 `profile` 字段是可选的
  • "个人资料必须始终连接到一个用户"

在前面的例子中,`Profile` 模型的 `user` 关系字段引用了 `User` 模型的 `id` 字段。您也可以引用不同的字段。在这种情况下,您需要用 `@unique` 属性标记该字段,以确保每个 `Profile` 只连接到一个 `User`。在下面的例子中,`user` 字段引用了 `User` 模型中的 `email` 字段,该字段用 `@unique` 属性标记。

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)
}
警告

在 MySQL 中,您可以在引用侧仅通过索引创建外键,而无需唯一约束。在 Prisma ORM 4.0.0 及更高版本中,如果您内省此类关系,将触发验证错误。要解决此问题,您需要向引用字段添加 `@unique` 约束。

关系数据库中的多字段关系

**仅在关系数据库中**,您还可以使用多字段 ID 来定义 1-1 关系。

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 关系

关系型数据库

以下示例演示了如何在 SQL 中创建 1-1 关系。

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 关系

以下示例演示了如何在 SQL 中使用复合键(`firstName` 和 `lastName`)创建 1-1 关系。

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 相互引用,方式类似于关系型数据库。

以下 MongoDB 文档表示一个 `User`。

{ "_id": { "$oid": "60d58e130011041800d209e1" }, "name": "Bob" }

以下 MongoDB 文档表示一个 `Profile` - 请注意 `userId` 字段,它引用了 `User` 文档的 `$oid`。

{
"_id": { "$oid": "60d58e140011041800d209e2" },
"bio": "I'm Bob, and I like drawing.",
"userId": { "$oid": "60d58e130011041800d209e1" }
}

必需和可选的 1-1 关系字段

在一对一关系中,关系**没有**关系标量的一方(在数据库中表示外键的字段)**必须**是可选的。

model User {
id Int @id @default(autoincrement())
profile Profile? // No relation scalar - must be optional
}

此限制在 2.12.0 版本中引入。

但是,您可以选择关系**带有**关系标量的一方应该是可选的还是强制的。

强制 1-1 关系

在以下示例中,`profile` 和 `profileId` 是强制的。这意味着您无法在不连接或创建 `Profile` 的情况下创建 `User`。

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 关系

在以下示例中,`profile` 和 `profileId` 是可选的。这意味着您可以在不连接或创建 `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 关系中存储外键

在 **1-1 关系**中,您可以自己决定要在关系哪一方使用 `@relation` 属性进行注解(从而持有外键)。

在以下示例中,`Profile` 模型上的关系字段用 `@relation` 属性进行了注解。`userId` 是底层数据库中外键的直接表示。

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)
}

您也可以用 `@relation` 属性注解关系的另一方。以下示例注解了 `User` 模型上的关系字段。`profileId` 是底层数据库中外键的直接表示。

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?
}
© . This site is unofficial and not affiliated with Prisma Data, Inc.