一對一關係
本頁面介紹一對一關係,並說明如何在您的 Prisma 結構描述中使用它們。
概觀
一對一 (1-1) 關係是指關係的雙方最多只能連接一個記錄。在下面的範例中,User
和 Profile
之間存在一對一關係
- 關聯式資料庫
- 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
關係純量是底層資料庫中外鍵的直接表示。這種一對一關係表示以下內容
- 「一個使用者可以有零個或一個個人資料」(因為
profile
欄位在User
上是選填的) - 「一個個人資料必須始終連接到一個使用者」
在先前的範例中,Profile
模型的 user
關係欄位參考了 User
模型的 id
欄位。您也可以參考不同的欄位。在這種情況下,您需要使用 @unique
屬性標記該欄位,以保證每個 Profile
僅連接到一個 User
。在以下範例中,user
欄位參考了 User
模型中標記有 @unique
屬性的 email
欄位
- 關聯式資料庫
- 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
約束新增至參考欄位。
關聯式資料庫中的多欄位關係
僅在關聯式資料庫中,您也可以使用多欄位 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 關係。
以下範例示範如何使用複合鍵 (firstName
和 lastName
) 在 SQL 中建立 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
是底層資料庫中外鍵的直接表示
- 關聯式資料庫
- 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
是底層資料庫中外鍵的直接表示
- 關聯式資料庫
- 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?
}