Prisma中findMany正常但deleteMany报错,如何处理标签删除逻辑?
解决Prisma删除仅关联单条笔记的标签时的MySQL 1093错误
问题背景
你定义了隐式多对多关联的Note和Tag模型:
model Tag { id Int @id @default(autoincrement()) tag String @unique notes Note[] } model Note { id Int @id @default(autoincrement()) note String @unique tags Tag[] }
删除单条笔记时,你尝试删除仅关联该笔记的标签,编写的deleteMany代码触发了MySQL 1093错误:
await prisma.tag.deleteMany({ where: { notes: { none: { tags: { some: { tag: { in: tags } } } } }, // tags为被删除笔记的标签数组 }, });
错误信息:
ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Server(ServerError { code: 1093, message: "You can't specify target table 'Tags' for update in FROM clause", state: "HY000" })) })
解决方案
方案1:先查询目标标签ID再批量删除
这是你当前使用的可靠方案,先通过findMany筛选出符合条件的标签ID,再执行批量删除:
// 获取仅关联被删除笔记的标签ID const targetTagIds = await prisma.tag.findMany({ where: { tag: { in: tags }, notes: { every: { id: deletedNoteId } } // 标签仅关联当前被删除的笔记 }, select: { id: true } }).then(res => res.map(item => item.id)); // 执行批量删除 await prisma.tag.deleteMany({ where: { id: { in: targetTagIds } } });
方案2:使用Prisma原生SQL执行嵌套查询
利用MySQL允许嵌套子查询的特性,通过$executeRawUnsafe执行原生SQL,直接完成删除操作:
await prisma.$executeRawUnsafe(` DELETE FROM Tag WHERE tag IN (?) AND (SELECT COUNT(*) FROM Note_Tag WHERE tagId = Tag.id) = 1 `, tags);
注:Note_Tag是Prisma隐式多对多生成的中间表,表名由两个模型名按字母顺序拼接生成,可根据实际情况调整。
方案3:优化Prisma查询条件规避自引用
调整deleteMany的查询条件,避免生成触发1093错误的SQL。核心逻辑是:标签属于被删除笔记的标签列表,且仅关联该笔记:
await prisma.tag.deleteMany({ where: { tag: { in: tags }, notes: { every: { id: deletedNoteId } } // 所有关联笔记都是当前被删除的那条 } });
该条件会让Prisma生成更合理的SQL,避免在删除语句的FROM子句中直接引用目标表,从而绕过1093错误。
错误原因说明
MySQL 1093错误本质是不允许在UPDATE/DELETE语句的FROM子句中直接引用目标表,而你最初的复杂关联查询导致Prisma生成了这类SQL,通过上述方案均可规避该限制。
内容的提问来源于stack exchange,提问作者VSS
相关产品推荐
相关产品推荐

