JDBC - INSERT 并返回生成的 id,或者如果 DUPLICATE KEY 返回旧 id

发布于 2024-12-09 16:59:49 字数 676 浏览 0 评论 0原文

标题已经说得很清楚了... 我希望能够将一个项目添加到数据库中,如果已经有一个项目具有匹配的唯一列,则返回该项目的 id...

的解决方案最接近

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

下面的表达式与我找到 使用statement. generatedKeys() 获得新的id(插入新行时)。 如果出现重复,“id”会出现在statement. generatedKeys() 中吗?如果没有,我怎样才能获取它?

更新:使用存储过程,以下正是我所需要的:

INSERT INTO applications (path, displayName) VALUES (?, ?) 
ON DUPLICATE KEY UPDATE 
   id = LAST_INSERT_ID(id), path = ?, displayName = ?;
SELECT LAST_INSERT_ID() INTO ?;

它适用于我正在开发的不同项目,该项目在.NET中使用MySQL连接器,但不幸的是存储过程不适合我这个Java项目。

有没有其他方法可以在同一个网络行程中发送 2 个语句?

The title is pretty clear...
I want to be able to add an item to the database, and in case there's already an item with a matching unique column, return that item's id...

The expression below is as close as I found to a solution

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

I was able to fetch the new id (when inserting a new row) using statement.generatedKeys().
will "id" appear in statement.generatedKeys() in case of duplicate? if not, how can I fetch it?

UPDATE : using stored procedure, the following is exactly what I need:

INSERT INTO applications (path, displayName) VALUES (?, ?) 
ON DUPLICATE KEY UPDATE 
   id = LAST_INSERT_ID(id), path = ?, displayName = ?;
SELECT LAST_INSERT_ID() INTO ?;

It works on different project i'm working on which uses MySQL Connector in .NET, but unfortunately Stored Procedure is not an option for me in this Java project.

Is there any other way I can send 2 statements in the same network trip?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦开始←不甜 2024-12-16 16:59:49

这看起来合法

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=3;

,但这看起来很疯狂:

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

您会更新现有记录的 ID 字段吗?引用此记录的那些记录会发生什么情况?

不管怎样,猜测在正常更新的情况下(第一个)statement. generatedKeys() 不会返回已经存在的 ID。
在这种情况下,您可能需要发出额外的 select 语句(在 where 子句中使用唯一键列:select id from table where a=1 and b=2)来查找记录。

或者,您也可以编写一个存储过程,在两种情况下插入/更新都会返回 ID。

This seems legit

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=3;

but this seems crazy:

INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

Would you update the ID field of an existing record? What will happen to those records referencing to this one?

Anyway, guess in case of a normal update (the forst one) statement.generatedKeys() wont return the already existing ID.
In this case you'll probably have to issue an additional select statement (with the unique key columns in the where clause: select id from table where a=1 and b=2) to find out ID of the record.

Or alternatively you could write a stored procedure which does the insert/update returns the ID in both case.

不打扰别人 2024-12-16 16:59:49

所以我的要求和OP一样。 Mysql 处理 INSERT...ON DUPLICATE KEY UPDATE 的方式很愚蠢,但不幸的是我们必须忍受它。当您在 Mysql 5.5 或更高版本上使用 ON DUPLICATE 时,如果插入没有重复,则 JDBC 将返回计数 1 和新插入行的 ID。如果所采取的操作是由于重复而进行的更新,则 JDBC 将返回计数 2 以及原始行的 ID 和新生成的 ID,即使新 ID 从未实际插入到表中。

您可以通过调用PreparedStatement.getGenerateKeys()来获取正确的密钥。第一个键几乎总是您感兴趣的键。因此,对于上面的示例:

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3;

您可以通过调用以下方式获取插入或更新的 ID:

Long key;
ResultSet keys = preparedStatement.getGeneratedKeys();
if (keys.next())
    key = keys.getLong("GENERATED_KEY");

So I just had the same requirement as the OP. The way Mysql handles INSERT...ON DUPLICATE KEY UPDATE is just asinine, but unfortunately we have to live with it. When you use ON DUPLICATE on Mysql 5.5 or above, if the insert happens without duplicate, JDBC returns count of 1 and the ID of the newly inserted row. If the action taken is an update due to duplicate, JDBC returns count of 2 and both the ID of the original row AND the newly generated ID, even though the new ID is never actually inserted into the table.

You can get the correct key by calling PreparedStatement.getGeneratedKeys(). The first key is pretty much always the one you are interested in. So with the above example:

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3;

You can get the inserted or updated ID by calling:

Long key;
ResultSet keys = preparedStatement.getGeneratedKeys();
if (keys.next())
    key = keys.getLong("GENERATED_KEY");
我做我的改变 2024-12-16 16:59:49

如果您的目标是防止重复记录,则可以使用主键/UNIQUE 约束< /a>.然后,您可以在代码中采用以下路径之一:

  1. 以编程方式检查要添加的行的唯一性,并处理该行已存在于表中的情况
  2. 尝试插入新行。如果它是重复的,则尝试将失败并出现异常,您可以使用相同的标准找到旧行。我认为这是一个糟糕的方法。

If your goal is to prevent duplicate records, you can set up your table with a primary key/UNIQUE constraint. You could then take one of the following paths in your code:

  1. Programmatically check for the uniqueness of the row you're about to add and handle the case where that row already exists in the table
  2. Try to insert the new row. If it's a duplicate, the attempt will fail with an exception and you can find the old row using the same criterion. I think this is a poor approach.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文