首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

JDBC PreparedStatement 占位符插入失敗:executeUpdate 重複傳遞 SQL 字串

     編輯:程式設計疑難解答

錯誤現象

程式碼:

String sql = "insert into User(name,password) values(?,?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, name);
st.setString(2, password);
int num = st.executeUpdate(sql); // ❌ 錯誤:再次傳遞 SQL 字串

拋出異常:MySQLSyntaxErrorException: ... syntax to use near '?,?)'

根本原因

PreparedStatement.executeUpdate(String sql) 簽名是針對 Statement 介面設計,會直接執行傳入的 SQL 字串,忽略先前設定的參數綁定。導致資料庫收到字面 insert into User(name,password) values(?,?),而非替換後的值,產生語法錯誤。

正確寫法

String sql = "insert into User(name,password) values(?,?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, name);
st.setString(2, password);
int num = st.executeUpdate(); // ✅ 正確:無參數版本,使用預編譯 SQL 與已綁定參數

PreparedStatement 核心方法對照

方法適用介面行為
executeUpdate()PreparedStatement執行預編譯 SQL,使用已綁定參數 ✅
executeUpdate(String sql)Statement直接執行字串 SQL,忽略參數綁定 ❌
executeQuery()PreparedStatement查詢操作,使用已綁定參數 ✅
execute()PreparedStatement通用執行,使用已綁定參數 ✅

完整正確範例 (含資源管理)

public static void insert(String name, String password) {
    String sql = "INSERT INTO User(name, password) VALUES(?, ?)";
    
    // try-with-resources 自動關閉資源 (JDBC 4.1+)
    try (Connection conn = DbUtils.getConn();
         PreparedStatement st = conn.prepareStatement(sql)) {
        
        st.setString(1, name);
        st.setString(2, password);
        
        int affectedRows = st.executeUpdate(); // 關鍵:無參數版本
        
        if (affectedRows > 0) {
            System.out.println("插入成功,影響行數: " + affectedRows);
        } else {
            System.out.println("插入失敗,無資料異動");
        }
        
    } catch (SQLException e) {
        System.err.println("資料庫操作異常: " + e.getMessage());
        e.printStackTrace();
        throw new RuntimeException("插入失敗", e);
    }
}

進階:批次插入效能優化

String sql = "INSERT INTO User(name, password) VALUES(?, ?)";
try (Connection conn = DbUtils.getConn();
     PreparedStatement st = conn.prepareStatement(sql)) {
    
    conn.setAutoCommit(false); // 關閉自動提交
    
    for (User user : userList) {
        st.setString(1, user.getName());
        st.setString(2, user.getPassword());
        st.addBatch(); // 加入批次
    }
    
    int[] results = st.executeBatch(); // 一次執行批次
    conn.commit(); // 手動提交
    
    System.out.println("批次插入完成,筆數: " + results.length);
}

常見錯誤對照表

錯誤代碼原因修正
MySQLSyntaxErrorException near '?,?'executeUpdate(sql) 重複傳遞 SQL改用 executeUpdate()
Parameter index out of rangesetString 索引超過 ? 數量檢查 SQL 佔位符數量與 set 索引對應
Data truncation欄位長度不足/型別不符調整資料庫結構或資料預處理
Connection is closedConnection 提前關閉調整 try-with-resources 範圍
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved