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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:20:18