当前位置: 首页 > 面试题库 >

Java PreparedStatement和ON DUPLICATE KEY UPDATE:我怎么知道是插入行还是更新行?

燕凯旋
2023-03-14
问题内容

具有以下代码,我如何知道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();

提前致谢。


问题答案:

考虑下面的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(在此进行描述),以下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. 尝试的INSERT被中止,因为这将导致重复的UNIQUE键值, 并且
  2. 指定的ON DUPLICATE KEY UPDATE更改 实际上不会修改现有行中的任何值

可以通过使用完全相同的参数值连续两次运行上述测试代码来确认这一点。请注意,UPDATE ... id = LAST_INSERT_ID(id)“技巧”确实可以确保id返回正确的值。

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



 类似资料:
  • 问题内容: 具有以下代码,我如何知道execute()方法是导致插入还是导致更新?: 提前致谢。 问题答案: 考虑下面的MySQL测试表: 现有的样本数据如下: 使用默认的连接设置(此处描述),以下Java代码 产生以下控制台输出 现在,再次使用参数值运行相同的代码 控制台输出是 这表明如果唯一索引导致现有行被更新,则实际上可以返回2。如果您需要有关 实际 测试代码的进一步帮助,则应编辑问题以包括

  • 问题内容: 我试图在网上找到答案,但是找不到特定于实现的答案。 我可以选择,并进行了大量的业务,我想知道我怎么可以在它们之间进行选择? 我已阅读文档的onComplete和的onSuccess,但我可以从火力地堡文档,看这一个,例如,对于(如一个具体操作的示例操作),他们有时用,有时他们使用。 我怎么知道每种情况下哪个更好?有关系吗?考虑到我想知道每个操作是否成功。 问题答案: 顾名思义,将在任务

  • 问题内容: 我用Java写了一个servlet,我想知道对该servlet的请求是使用HTTP还是HTTPS执行的。 我以为可以使用,但是两种方法都返回HTTP / 1.1。 有任何想法吗? 问题答案: *_答案是 _ *HttpSerlvetRequest.isSecure() 。在以下情况下,ServletContainer负责返回true: ServletContainer本身是否可以接受h

  • 问题内容: 我们有一个数据库,每天cronjob在午夜更新,我们从外部XML获取新数据。 我们要做的是插入所有新内容,并在键重复的情况下更新该字段。 我们想知道的是实际插入了哪些行,这意味着我们想要一个新项目的列表。是否有可能返回新插入的查询?基本上,我们将需要获取所有新的ID,而不是新插入的数量。 谢谢 问题答案: 添加一列并更改您的查询: 您也可以在触发器中增加它,使您可以保持查询不变。

  • Jenkins有600个插件,在实际系统中,我们用来安装大量的插件。 有时,我们想删除一些插件,使系统更干净,或者用另一个成熟的插件(不同的名称)替换。 这需要确保没有人/没有工作使用这些插件,或者我需要通知他们。 在Jenkins系统的配置或某处是否有任何方法可以知道插件是否被任何作业使用? 更新2013基于下面的答案,我维护简单的“plugin:keyword”映射,如 并从中搜索插件关键字,

  • 问题内容: 我在做一个用用java Postgres的。有什么方法可以确定是插入行还是更新行? 问题答案: 您可以查看“系统”列来说明不同之处。在这种情况下,它用于插入的行。 这是建立在未记录的实现细节上的,该细节在将来的版本中可能会更改(即使可能性不大)。它适用于Postgres 9.5和9.6。 它的优点:您无需引入其他列。