Prisma关联查询authors时触发MySQL预编译语句占位符过多错误
解决Prisma查询时出现MySQL 1390错误(Prepared statement contains too many placeholders)
错误原因
MySQL默认限制预处理语句的占位符数量为65535,当你一次性查询10万条图书并关联authors时,Prisma会生成包含大量占位符的批量关联查询SQL,超出这个限制就触发1390错误。即使authors字段少,关联查询的实现方式也会导致占位符累加超标。
解决方案
1. 分页查询(推荐)
分批次获取数据,控制每次查询的数量,避免单次查询生成过多占位符:
const batchSize = 1000; let allBooks = []; let skip = 0; while (true) { const batch = await prisma.book.findMany({ include: { authors: true }, take: batchSize, skip: skip, }); if (batch.length === 0) break; allBooks = [...allBooks, ...batch]; skip += batchSize; }
可根据服务器性能调整batchSize(如500或2000),确保每次查询的占位符数量在MySQL限制内。
2. 调整MySQL配置参数
修改MySQL的max_prepared_stmt_count参数,增大允许的预处理语句占位符数量:
- 找到MySQL配置文件(my.cnf或my.ini),添加或修改:
max_prepared_stmt_count = 1000000
- 重启MySQL服务生效。
注意:此方法会增加服务器内存消耗,大量数据一次性查询可能引发性能问题,需谨慎使用。
3. 精简返回字段
明确指定需要查询的字段,减少数据量和占位符数量:
let books = await prisma.book.findMany({ select: { // 只保留业务需要的图书字段 id: true, title: true, publicationDate: true, authors: { select: { fullname: true, }, }, }, });
通过select替代include的全字段查询,能有效减少占位符生成数量,可能刚好控制在限制范围内。
4. 使用原生SQL查询
用Prisma的原生SQL编写JOIN查询,替代默认的批量关联查询逻辑:
const rawBooks = await prisma.$queryRaw` SELECT b.id, b.title, a.fullname FROM Book b LEFT JOIN Author a ON b.authorId = a.id `; // 手动整理结果结构,将同一图书的authors合并为数组 const books = rawBooks.reduce((acc, item) => { const existing = acc.find(book => book.id === item.id); if (existing) { existing.authors.push({ fullname: item.fullname }); } else { acc.push({ id: item.id, title: item.title, authors: [{ fullname: item.fullname }], }); } return acc; }, []);
这种方式更灵活,直接控制SQL的关联逻辑,避免占位符过多的问题。
内容的提问来源于stack exchange,提问作者StykPohlavsson
相关产品推荐
相关产品推荐

