Prisma/MySQL无法删除关联ReviewImages的Review记录求助
我有User、Restaurant、Review、ReviewImages四张数据表。用户给餐厅撰写带图评论时,评论内容存入Review记录,图片存入ReviewImages记录。现在遇到的问题是删除Review记录必须先手动删除关联的ReviewImages记录,用Prisma Studio直接删Review时触发以下错误:
Type: undefined
Message:
Invalidprisma.reviews.delete()invocation:Foreign key constraint failed on the field:
reviewIdCode: P2003
Query:
[object Object]
我怀疑是ReviewImages的关联配置出了问题,附上对应的Prisma Schema代码:
model User { id String @id @default(cuid()) name String nickname String? @unique bobId String? @unique email String @unique emailVerified DateTime? image String? @db.VarChar(500) title String? description String? @db.VarChar(500) accounts Account[] sessions Session[] VisitedRestaurants VisitedRestaurants[] Reviews Reviews[] ReviewImages ReviewImages[] ReviewLikes ReviewLikes[] ReviewComments ReviewComments[] } model Restaurants { id String @id @db.VarChar(50) poi_nm String @db.VarChar(100) branch_nm String? @db.VarChar(100) sub_nm String? @db.VarChar(100) mcate_cd String? @db.VarChar(30) mcate_nm String? @db.VarChar(200) pnu String? @db.VarChar(30) sido_nm String? @db.VarChar(100) sgg_nm String? @db.VarChar(100) bemd_nm String? @db.VarChar(100) ri_nm String? @db.VarChar(100) beonji String? @db.VarChar(20) badm_cd String? @db.VarChar(30) hadm_cd String? @db.VarChar(30) rd_cd String? @db.VarChar(30) rd_nm String? @db.VarChar(100) bld_num String? @db.VarChar(30) grid_cd String? @db.VarChar(30) origin String? @db.VarChar(200) base_ymd String? @db.VarChar(20) createdAt DateTime @default(now()) loc Unsupported("point") Reviews Reviews[] VisitedRestaurants VisitedRestaurants[] ReviewImages ReviewImages[] @@index(loc, map: "loc") } model Reviews { id String @unique @default(cuid()) user User @relation(fields: [userId], references: [id]) userId String @db.VarChar(255) restaurant Restaurants @relation(fields: [restaurantId], references: [id]) restaurantId String @db.VarChar(50) title String @db.VarChar(300) titleLink String @unique @db.VarChar(500) content String @db.Text preview String @db.VarChar(255) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt ReviewImages ReviewImages[] ReviewLikes ReviewLikes[] ReviewComments ReviewComments[] @@id([userId, restaurantId]) } model ReviewImages { id String @id @default(cuid()) urls String @db.Text user User @relation(fields: [userId], references: [id]) userId String review Reviews @relation(fields: [reviewId], references: [id], onDelete: Cascade) reviewId String restaurant Restaurants @relation(fields: [restaurantId], references: [id]) restaurantId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }
你的Reviews模型用了复合主键@@id([userId, restaurantId]),但ReviewImages里的reviewId关联的是Reviews的id字段(这个字段仅标记了@unique,不是主键)。数据库层面的外键约束实际指向的是Reviews的复合主键,而非你定义的id字段,导致配置的onDelete: Cascade没有生效。
有两种可行的解决方式:
方案一:调整Reviews的主键规则
把Reviews的主键改成单独的id字段,将原来的复合主键改成唯一约束(保证一个用户对同一家餐厅只能写一条评论):
model Reviews { id String @id @default(cuid()) // 设为主键 user User @relation(fields: [userId], references: [id]) userId String @db.VarChar(255) restaurant Restaurants @relation(fields: [restaurantId], references: [id]) restaurantId String @db.VarChar(50) title String @db.VarChar(300) titleLink String @unique @db.VarChar(500) content String @db.Text preview String @db.VarChar(255) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt ReviewImages ReviewImages[] ReviewLikes ReviewLikes[] ReviewComments ReviewComments[] // 用唯一约束替代原复合主键,保证用户-餐厅评论唯一性 @@unique([userId, restaurantId]) }
这样ReviewImages里的reviewId就能正确关联到Reviews的主键id,onDelete: Cascade会正常工作,删除Review时会自动删除关联的ReviewImages。
方案二:调整ReviewImages的关联字段
如果要保留Reviews的复合主键,需要修改ReviewImages的关联配置,用复合外键指向Reviews的复合主键:
model ReviewImages { id String @id @default(cuid()) urls String @db.Text user User @relation(fields: [userId], references: [id]) userId String review Reviews @relation(fields: [userId, restaurantId], references: [userId, restaurantId], onDelete: Cascade) // 移除单独的reviewId,用userId+restaurantId作为复合外键关联Reviews restaurant Restaurants @relation(fields: [restaurantId], references: [id]) restaurantId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }
保留Reviews的@@id([userId, restaurantId])配置,这样外键约束会正确关联到复合主键,删除Review时会级联删除对应的ReviewImages。
修改Schema后,需要运行prisma migrate dev命令同步数据库结构,确保新的约束生效。
内容的提问来源于stack exchange,提问作者Intaek

