TL;DR
@id
は一つのフィールドの値をそのまま主キーにしたいときに使う属性です。
@@id
は、複数のフィールドの値を組み合わせた値を主キーにしたいときに使う属性です。
@id
を使ったサンプルコード
model User {
id String @id
name String
}
const newUser = await prisma.user.create({
data: {
id: 1,
name: 'Alice',
},
})
上記のコードでnewUserを作成した場合、このnewUserの主キーidは1になります。
そのため、以下のコードで一意のuserを探すことができます。
const user = await prisma.user.findUnique({
where: {
id: 1,
})
@@id
を使ったサンプルコード
model User {
id String
name String
@@id([id, name])
}
const newUser = await prisma.user.create({
data: {
id: 1,
name: 'Alice',
},
})
上記のコードでnewUserを作成した場合、newUserの主キーid_nameは、1_Aliceになります。
そのため、以下のコードで一意のuserを探すことができます。
const user = await prisma.user.findUnique({
where: {
id_name: {
id: 1,
name: 'Alice',
},
},
})
そもそも@と@@の違い
属性は、フィールドやブロックの動きを編集するのですが、データモデルに属性を追加するのには2つの方法があります。
フィールドに対して属性を追加するなら、属性の頭に@
をつけます。
ブロックに対して属性を追加するなら、属性の頭に@@
をつけます。
@id
と@@id
の他に、@map
と@@map
のような属性も存在します。
ここから下は意見です。
複合主キーのデメリット
主キーとして用いているフィールドの値に修正が入った場合に、修正コストが高いです。
例えば、Aliceさんが名前を、Bobさんに変更した場合は1_Alice
が1_Bob
に変更になります。
外部テーブルからこのレコードが参照されている場合、そちらも変更する必要があります。
@id
と@@id
のどちらを使うべき?
複合主キーのフィールドの値が二度と変更されない場合は、複合主キーを使っても良いです。
例えば、下記のような中間テーブルでは、postIdとuserIdは変更される可能性が低いので使うことができます。
model Like {
postId String
userId String
@@id([postId, userId])
}
しかし、基本的には、サロゲートキーを使うべきです。
参考文献
https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#remarks-5
https://scrapbox.io/mrsekut-p/サロゲートキー_v.s._複合主キーでは、前者を選ぶ
https://zenn.dev/kaz_z/articles/prisma-unique-key
https://scrapbox.io/mrsekut-p/ナチュラルキーがある時はサロゲートキーは不要