You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prisma/MySQL无法删除关联ReviewImages的Review记录求助

问题描述

我有User、Restaurant、Review、ReviewImages四张数据表。用户给餐厅撰写带图评论时,评论内容存入Review记录,图片存入ReviewImages记录。现在遇到的问题是删除Review记录必须先手动删除关联的ReviewImages记录,用Prisma Studio直接删Review时触发以下错误:

Type: undefined
Message:
Invalid prisma.reviews.delete() invocation:

Foreign key constraint failed on the field: reviewId

Code: 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:55:18