Node.js读取JSON批量插入PostgreSQL出现语法错误问题排查
问题原因
pg-format批量插入要求传入二维数组,你当前的intakes是对象数组,直接用%L格式化时会把每个对象整体序列化为字符串,而非将对象属性拆分为单独的字段值,导致SQL中出现一整个被单引号包裹的JSON字符串,直接触发语法错误。- 调用
client.query时重复传入了intakes参数:你已经通过pg-format把值拼接进SQL语句,不需要再传第二个参数,否则pg会将其识别为预编译占位符的对应值,引发额外语法问题。 - 存在冗余导入:第一行
const pg = require('pg');和第二行const { Pool } = require('pg');功能重复,可以合并。
解决办法
首先将对象数组转换为二维数组,每个子数组对应一条记录的字段值,顺序要和INSERT语句中的字段顺序完全对应,之后修正SQL生成逻辑和查询调用即可,修正后的代码如下:
const { Pool } = require('pg'); const format = require('pg-format'); const fs = require('fs'); // 读取并解析JSON文件 const rawintakes = fs.readFileSync('./data/intakes.json', 'utf8'); const intakes = JSON.parse(rawintakes); // 转换为pg-format要求的二维数组结构,字段顺序和INSERT声明的顺序严格对齐 const values = intakes.map(item => [ item.Archived, item.ClientEmail, item.ClientId, item.ClientName, item.DateCreated, item.DateSubmitted, item.ExternalClientId, item.Id, item.Practitioner, item.PractitionerId, item.PractitionerName, item.QuestionnaireId, item.QuestionnaireName, item.Status ]); // 生成合法的批量插入SQL const query1 = format('INSERT INTO intake_summary (Archived, ClientEmail, ClientId, ClientName, DateCreated, DateSubmitted, ExternalClientId, Id, Practitioner, PractitionerId, PractitionerName, QuestionnaireId, QuestionnaireName, Status) VALUES %L returning id', values); async function run() { let client; try { client = new Pool({ connectionString: 'postgres://postres:reallystrongpassword@localhost:5432/cldba01' }); await client.connect(); // 已拼接好SQL,无需传入第二个参数 const {rows} = await client.query(query1); console.log(rows); } catch (e) { console.error(e); } finally { client.end(); } } run();
如果需要规避SQL注入风险,也可以改用pg的预编译批量插入语法,通过生成对应数量的$n占位符或者调用unnest函数实现,上述写法已经可以解决你当前遇到的报错问题。
内容的提问来源于stack exchange,提问作者Tex Evans
相关产品推荐
相关产品推荐

