AppScript生成JSON插入PostgreSQL失败:Node.js代码故障排查
问题排查:Node.js无法将AppScript生成的JSON插入PostgreSQL
我编写的Node.js代码无法将AppScript生成的JSON数据插入PostgreSQL数据库。单独打印JSON显示正常,数据库连接也能正常查询已有数据,但数据始终无法入库。已核对字段名与数据类型,仍未找到问题所在,相关代码如下:
const { Client } = require('pg'); const fetch = require('node-fetch').default; const obtenerItinera = async () => { const client = new Client({ user: 'postgres', host: 'localhost', database: 'pruebas', password: '123456', port: 5432, }); await client.connect(); const res = await client.query('SELECT * FROM datos_generales'); const result = res.rows; await client.end(); return result; }; const insertarDatos = async (data) => { const client = new Client({ user: 'postgres', host: 'localhost', database: 'pruebas', password: '123456', port: 5432, }); await client.connect(); for (let i = 0; i < data.length; i++) { const row = data[i]; // Verificar si la fila ya existe en la base de datos por su valor de vuelo try { const res = await client.query('SELECT COUNT(*) FROM datos_generales WHERE vuelo = $1', [row.vuelo]); const count = parseInt(res.rows[0].count); if (count === 0) { // La fila no existe en la base de datos, realizar la inserción console.log('Insertando fila:', row); await client.query(`INSERT INTO datos_generales (vuelo, eta, etd, ata, atd) VALUES ($1, $2, $3, $4, $5)`, [row.vuelo, row.eta, row.etd, row.ata, row.atd]); console.log('Fila insertada:', row); } else { console.log('La fila ya existe en la base de datos, omitiendo inserción:', row); } } catch (error) { console.error('Error al realizar la inserción:', error); } } const res = await client.query('SELECT * FROM datos_generales'); const result = res.rows; await client.end(); return result; }; async function downloadJSON() { // el link fue cortado const url = 'https://script.google.com/macros/s/exec'; // Reemplaza con la URL real tu API try { const response = await fetch(url); const data = await response.json(); // Insertar los datos en la base de datos const resultadoInsercion = await insertarDatos(data); console.log('Datos insertados:', resultadoInsercion); // Realizar la consulta SELECT * después de agregar los datos const resultadoConsulta = await obtenerItinera(); console.log('Datos obtenidos:', resultadoConsulta); } catch (error) { console.error('Error al descargar el JSON o insertar los datos:', error); } // Programar la próxima descarga después de 5 segundos setTimeout(downloadJSON, 5000); } // Iniciar la descarga inicial downloadJSON();
排查方向与修复建议
1. 增强错误日志定位问题
当前insertarDatos函数的catch块仅打印错误信息,无法关联到具体出错的行数据。修改catch块,补充打印当前处理的行内容,方便定位具体哪条数据出问题:
catch (error) { console.error('Error al insertar fila:', row, '\nDetalles:', error); }
2. 校验字段名与数据类型的隐性不匹配
- 确认AppScript返回的JSON字段名大小写完全匹配数据库字段:比如数据库是
vuelo,JSON里不能是Vuelo或VUELO; - 检查日期字段(
eta/etd/ata/atd)的格式:PostgreSQL的timestamp/timestamptz类型要求严格的日期格式(如YYYY-MM-DD HH:MI:SS或ISO格式YYYY-MM-DDTHH:MI:SSZ),如果AppScript返回的是其他格式(如DD/MM/YYYY),需要手动转换:// 示例:将字符串日期转换为ISO格式 const formatDate = (dateStr) => { if (!dateStr) return null; return new Date(dateStr).toISOString(); }; // 插入时替换日期字段 await client.query( `INSERT INTO datos_generales (vuelo, eta, etd, ata, atd) VALUES ($1, $2, $3, $4, $5)`, [row.vuelo, formatDate(row.eta), formatDate(row.etd), formatDate(row.ata), formatDate(row.atd)] );
3. 修复重复检查逻辑的潜在问题
- 如果
vuelo字段可能为null或空字符串,COUNT(*)的判断会失效(因为NULL = NULL在SQL中不成立),修改查询语句:const res = await client.query(` SELECT COUNT(*) FROM datos_generales WHERE (vuelo = $1 OR (vuelo IS NULL AND $1 IS NULL)) `, [row.vuelo]); - 确认
vuelo字段的数据类型完全匹配:比如数据库是INT类型,JSON返回的row.vuelo不能是字符串类型(需转换为数字:parseInt(row.vuelo))。
4. 验证插入语句的执行结果
可以通过client.query的返回结果确认插入是否成功,比如打印受影响的行数:
const insertRes = await client.query( `INSERT INTO datos_generales (vuelo, eta, etd, ata, atd) VALUES ($1, $2, $3, $4, $5)`, [row.vuelo, row.eta, row.etd, row.ata, row.atd] ); console.log('Fila insertada, filas afectadas:', insertRes.rowCount);
5. 优化数据库连接复用
当前每次调用obtenerItinera和insertarDatos都新建连接,建议复用单个客户端连接,减少资源消耗:
// 全局创建客户端连接 const client = new Client({ user: 'postgres', host: 'localhost', database: 'pruebas', password: '123456', port: 5432, }); // 初始化连接 async function initDB() { await client.connect(); console.log('Conectado a PostgreSQL'); } // 修改obtenerItinera,不再创建新连接 const obtenerItinera = async () => { const res = await client.query('SELECT * FROM datos_generales'); return res.rows; }; // insertarDatos同理,去掉新建client的代码,直接用全局client
内容的提问来源于stack exchange,提问作者MEX0001
相关产品推荐
相关产品推荐

