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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:02:41