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

处理req.body数组数据实现关联表批量插入报错求助

问题描述

我有表a和表b,需要同时创建两类数据,表b以表a的id作为外键,要批量向表b插入多行数据。从req.body接收的数据格式如下:

{
    "userId": 1,
    "a1": "ccc",
    "a2": "ddd",
    "typeId": [1, 2, 3],
    "count": [60, 100, 5]
}

期望生成的SQL插入语句格式:

INSERT INTO data (a_id,typeId,count)
  VALUES (0,1,60), (0,2,100), (0,3,5)

我尝试了两段DAO代码,但都报错:

第一段代码及报错

const createRecordData = async(userId, a1, a2, typeId, count) => {
  await myDataSource.query(
    `INSERT INTO a (user_id,a1,a2)
  VALUES(?,?,?)`,
    [userId, a1, a2]
  );

  const datas = await myDataSource.query(
    `INSERT INTO data (a_id,typeId,count)
  VALUES ${typeId.map((tID) =>"(" + "((SELECT 1939616)" + "," + tID + "," + count.map((c) => c + ")" ).join(","))}`,
    [typeId, count]
  );
  return data;
};

报错信息:

SyntaxError: Unexpected string in JSON at position 101

第二段代码及报错

const createRecordData = async(userId, a1, a2, typeId, count) => {
  await myDataSource.query(
    `INSERT INTO a (user_id,a1,a2)
  VALUES(?,?,?)`,
    [userId, a1, a2]
  );

const typeAndCount = typeId.map((type, index) => `((SELECT 1939616),${type},${count[index]}),`).join("");
  const datas = await myDataSource.query(
    `INSERT INTO data (a_id,typeId,count)
  VALUES ${typeAndCount}`,
    [typeId, count]
  );
  return data;
};

报错信息:

"typeId.map is not a function"

错误分析及解决方法

1. 第二段代码报错原因

typeId.map is not a function说明typeId不是数组类型。大概率是调用createRecordData时参数传递错误——比如解构req.body时出错,或者传递了非数组值给typeId。

解决:检查函数调用处,确保正确传递数组参数:

const { userId, a1, a2, typeId, count } = req.body;
await createRecordData(userId, a1, a2, typeId, count);

2. 第一段代码的SQL语法错误

拼接VALUES部分时逻辑混乱:内层count.map会把所有count值塞进每个typeId对应的括号,生成非法SQL结构(比如((SELECT 1939616),1,60),(100),(5))),触发JSON解析错误。

3. 通用问题:硬编码外键、SQL注入风险、未获取真实自增ID

  • 硬编码SELECT 1939616作为a_id,正确做法是插入表a后获取其自增id;
  • 直接拼接字符串生成SQL存在SQL注入风险,必须用参数化查询;
  • 函数返回值错误(返回未定义的data,应为datas)。

正确实现代码

const createRecordData = async(userId, a1, a2, typeId, count) => {
  // 校验数组长度一致
  if (typeId.length !== count.length) {
    throw new Error('typeId和count数组长度不匹配');
  }

  // 插入表a并获取自增id(不同数据库获取方式:MySQL用insertId,PostgreSQL用returning)
  const [insertAResult] = await myDataSource.query(
    `INSERT INTO a (user_id,a1,a2) VALUES(?,?,?)`,
    [userId, a1, a2]
  );
  const aId = insertAResult.insertId;

  // 生成参数化占位符和参数数组
  const placeholders = typeId.map(() => "(?,?,?)").join(",");
  const params = [];
  typeId.forEach((type, index) => {
    params.push(aId, type, count[index]);
  });

  // 执行批量插入
  const datas = await myDataSource.query(
    `INSERT INTO data (a_id,typeId,count) VALUES ${placeholders}`,
    params
  );
  return datas;
};

关键优化点

  • 获取表a真实自增id作为外键,避免硬编码;
  • 使用参数化占位符?生成SQL,彻底规避SQL注入;
  • 增加数组长度校验,避免数据不匹配;
  • 修复返回值错误。

内容的提问来源于stack exchange,提问作者ggyoE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:25:25