Java PreparedStatement和ON DUPLICATE KEY UPDATE:如何知道是否插入或更新了行?

时间:2014-03-30 11:36:42

标签: java mysql sql database jdbc

如果有以下代码,我如何知道execute()方法是否导致插入或更新?:

Connection c = DriverManager.getConnection(connectionString);

PreparedStatement st = c.prepareStatement("INSERT INTO `table`(`field1`) VALUES (?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);");

st.setString(1,"some value");
st.execute();

提前致谢。

2 个答案:

答案 0 :(得分:8)

考虑以下MySQL测试表:

CREATE TABLE `customers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

现有样本数据如下:

id  name            email
--  --------------  ----------------
 1  Loblaw, Bob     bob@example.com
 2  Thompson, Gord  gord@example.com

使用默认连接设置compensateOnDuplicateKeyUpdateCounts=false(描述here)以下Java代码

PreparedStatement ps = dbConnection.prepareStatement(
        "INSERT INTO customers (name, email) " +
        "VALUES (?, ?) " +
        "ON DUPLICATE KEY UPDATE " +
            "name = VALUES(name), " +
            "id = LAST_INSERT_ID(id)");
ps.setString(1, "McMack, Mike");
ps.setString(2, "mike@example.com");
int euReturnValue = ps.executeUpdate();
System.out.printf("executeUpdate returned %d%n", euReturnValue);
Statement s = dbConnection.createStatement();
ResultSet rs = s.executeQuery("SELECT LAST_INSERT_ID() AS n");
rs.next();
int affectedId = rs.getInt(1);
if (euReturnValue == 1) {
    System.out.printf("    => A new row was inserted: id=%d%n", affectedId);
}
else {
    System.out.printf("    => An existing row was updated: id=%d%n", affectedId);
}

生成以下控制台输出

executeUpdate returned 1
    => A new row was inserted: id=3

现在使用参数值

再次运行相同的代码
ps.setString(1, "Loblaw, Robert");
ps.setString(2, "bob@example.com");

,控制台输出

executeUpdate returned 2
    => An existing row was updated: id=1

这表明如果唯一索引导致现有行更新,.executeUpdate确实可以返回2。如果您的实际测试代码需要进一步的帮助,那么您应该编辑您的问题以包含它。

修改

进一步测试显示.executeUpdate如果

将返回1
  1. 尝试的INSERT被中止,因为它会导致重复的UNIQUE键值,
  2. 指定的ON DUPLICATE KEY UPDATE更改实际上不会修改现有行中的任何值
  3. 这可以通过使用完全相同的参数值连续两次运行上述测试代码来确认。请注意UPDATE ... id = LAST_INSERT_ID(id)"技巧"确保返回正确的id值。

    如果插入的唯一值是UNIQUE键值,这可能解释了OP的测试结果。

答案 1 :(得分:1)

使用executeUpdate代替,因为它会返回int行数。

更新1 :根据MySQL INSERT ... ON DUPLICATE KEY UPDATE documentation

  

如果ON DUPLICATE KEY UPDATE,则每行的受影响行值为1   该行将作为新行插入,如果现有行已更新,则为2。

更新2 INSERT IGNORE也可能是option

INSERT IGNORE INTO `table`(`field1`) VALUES (?)
插入新行时

executeUpdate应返回1,重复时应返回0。