Google Script中JDBC prepareStatement执行无报错但MySQL数据插入失败的问题求助
问题分析与代码修正
嘿,我帮你找出几个核心问题了,这就是为啥数据没插入还没报错的原因:
1. 致命的SQL语法错误
你在prepareStatement里写的SQL末尾多了, true,这完全不符合MySQL的INSERT语法,直接导致整个语句无效。这部分必须删掉!
2. 循环条件根本不成立
for (var i=0; i<sqlData; i++)这里,sqlData是一个数组,和数字比较时会被转换成NaN,循环条件永远不满足,所以addBatch()一次都没执行,executeBatch()返回长度0就很正常了。你得改成i < sqlData.length才能遍历所有数据。
3. 获取自增主键的方式错误
你注释里的Statement.RETURN_GENERATED_KEYS是要作为prepareStatement的第二个参数传入,而不是拼在SQL语句里的。
下面是修正后的完整代码,我还加了一些实用细节(比如事务回滚、安全关闭资源、获取自增主键的示例):
function sqlInsertEntities(){ const conn = sqlGetConnection(); if (!conn) { return; } // 先检查连接是否成功! ... var sqlData = filteredData.map(arrangeCols); // 映射为与MySQL列顺序一致的格式 Logger.log(sqlData); /** 日志输出符合预期: * [ [1.0, SSLPA, Sietel Ltd, 7.0, ASX:SSLPA], [1.0, WHFPA, Whitefield Ltd, 7.0, ASX:WHFPA], * [4.0, XTL, S&P/ASX 20, 7.0, INDEXASX:XTL], [4.0, XFL, S&P/ASX 50, 7.0, INDEXASX:XFL] ] */ try { conn.setAutoCommit(false); // 修正SQL语句,添加RETURN_GENERATED_KEYS参数获取自增主键 var sql = 'INSERT INTO entity (entity_type_id, entity_code, entity_name, exchange_id, googlefinance_ticker) VALUES (?, ?, ?, ?, ?)'; var stmt = conn.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS); // 修正循环条件:遍历数组的所有元素 for (var i=0; i < sqlData.length; i++) { // 注意:sqlData里的数值是1.0、7.0这种浮点数,转int没问题,若后续有非整数需改用setDouble stmt.setInt(1, sqlData[i][0]); stmt.setString(2, sqlData[i][1]); stmt.setString(3, sqlData[i][2]); stmt.setInt(4, sqlData[i][3]); stmt.setString(5, sqlData[i][4]); stmt.addBatch(); } var batchResults = stmt.executeBatch(); conn.commit(); Logger.log('成功插入行数:' + batchResults.length); // 如果需要获取插入后的自增主键,可参考这段代码 var generatedKeys = stmt.getGeneratedKeys(); var keys = []; while (generatedKeys.next()) { keys.push(generatedKeys.getInt(1)); // 假设自增主键是表的第一列,根据你的表结构调整 } Logger.log('生成的自增主键列表:' + keys.join(',')); } catch (e) { // 出错一定要回滚事务,避免数据不一致或连接资源泄漏 if (conn) { try { conn.rollback(); } catch (ignore) {} } Logger.log('Error: ' + e + ' : ' + e.getMessage() + '\nline: ' + e.lineNumber); Browser.msgBox('Error', e + ' : ' + e.getMessage() + '\\nline: ' + e.lineNumber, Browser.Buttons.OK); } finally { // 安全关闭资源:先判断对象是否存在,避免空指针异常 if (stmt) { try { stmt.close(); } catch (ignore) {} } if (conn) { try { conn.close(); } catch (ignore) {} } } }
额外的几个注意点:
- 事务回滚:出错时一定要调用
rollback(),不然可能导致事务挂起,占用数据库连接资源。 - 资源关闭:finally块里要先判断对象是否存在再关闭,避免抛出额外异常掩盖原始错误。
- 数据类型匹配:你的
sqlData里的ID是浮点数(比如1.0),用setInt会自动转成整数,没问题,但如果后续有非整数的ID值,要改成setDouble或者对应的数据类型方法。 - SQL注入风险:尽量不要直接拼接表名/列名,这里你用固定表名没问题,但如果是动态生成的表名,要格外注意安全(JDBC的参数只能用于值,不能用于表名/列名)。
内容的提问来源于stack exchange,提问作者maxhugen
相关产品推荐
相关产品推荐

