Prepared Statement syntax for ON DUPLICATE KEY UPDATE (number of params error)

KisnardOnline picture KisnardOnline · Apr 2, 2013 · Viewed 10.6k times · Source

Here is what I am trying to do. I want to insert into this table or update the record if the primary key(entity_id) exists. I am just having an issue with the SQL syntax. It wont let me have more params than the first amount of 'VALUES' so I get the following error:

Parameter index out of range (7 > number of parameters, which is 6).

int insertOrUpdateSuccess = MyDBSyncher.UPDATE("INSERT INTO " + DB_NAME + ".entities " +
    "(`entity_id`, `wai_type`, `wai_id`, `character_id`, `looted`, `creation_time`) " +
    "VALUES ((?), (?), (?), (?), (?), (?)) " +
    "ON DUPLICATE KEY UPDATE " +
    "`wai_type`='(?)', `wai_id`='(?)', `character_id`='(?)', `looted`='(?)'", 
    new String[]{tmpEntityId, values[0], values[1], values[2], values[3], values[4],
    values[0], values[1], values[2], values[3]});

This is kind of similar I think to what I am asking but I could not interpret it for my needs. Sorry to possibly post a duplicate.

Ohh and here is the UPDATE() function in my code:

public static int UPDATE(String updateStatement, String[] params){
    try {
        if(!conn.isClosed()) {
            logger.trace("Successfully connected to MySQL server using TCP/IP - " + conn);

            stat = conn.prepareStatement(updateStatement);
            for (int i = 0; i < params.length; i++){
                stat.setString(i+1, params[i]);
            }
            return stat.executeUpdate();
        }
    } catch(SQLException eSQL) {
        logger.fatal(eSQL.getMessage());
    }
    return -1;
}

Thanks for any help with this. :)

Answer

sactiw picture sactiw · Mar 27, 2014

Why not just get rid of putting binding param in the duplicated values itself that is following query:

INSERT INTO mytable (col1, col2, col3) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE col1=?, col2=?, col3=?;

Can be re-written as:

INSERT INTO mytable (col1, col2, col3) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2), col3=VALUES(col3);

IMO one should prefer 2nd over 1st because:

  • not using binding param for 'ON DUPLICATE KEY UPDATE' part in the query means you don't have to write extra piece of code (or iteration in your case) to bind them

  • writing less code means fewer chances of making binding errors (typos etc.)

  • it has better readability