在MySQL中,如何仅在行不存在时插入并仅在现有版本较少时更新
我正在寻找一种方法,仅在 MySQL 中不存在该行时插入,并在该行存在并且现有行的版本小于(或等于)新行的版本时更新。
例如,该表定义为:
CREATE TABLE documents (
id VARCHAR(64) NOT NULL,
version BIGINT UNSIGNED NOT NULL,
data BLOB,
PRIMARY KEY (id)
);
并包含以下数据:
id version data
----------------------------
1 3 first data set
2 2 second data set
3 5 third data set
我想合并下表(更新:id 列是唯一的):
id version data
----------------------------
1 4 updated 1st
3 3 updated 2nd
4 1 new 4th
它应该生成以下内容(更新:看看如何仅更新 1 和 4插入):
id version data
----------------------------
1 4 updated 1st
2 2 second data set
3 5 third data set
4 1 new 4th
我查看了 INSERT ... ON DUPLICATE KEY UPDATE ... 语句,但它不允许某种 WHERE 子句。另外,我不能真正使用 REPLACE 因为它也不允许 WHERE。这甚至可以通过单个 MySQL 语句实现吗?
我正在使用 Java,并尝试使用 PreparedStatement 与批处理 (addBatch)。任何帮助将不胜感激。
更新:有什么方法可以将此查询与Java中的PreparedStatement一起使用吗?我有一个包含 id、版本和数据的 Document 对象列表。
I am looking for a way to only insert when the row does not exist in MySQL, and update when the row exists AND the version of the existing row is less than (or equal to) the version of the new row.
For example, the table is defined as:
CREATE TABLE documents (
id VARCHAR(64) NOT NULL,
version BIGINT UNSIGNED NOT NULL,
data BLOB,
PRIMARY KEY (id)
);
And contains the following data:
id version data
----------------------------
1 3 first data set
2 2 second data set
3 5 third data set
And I want to merge the following table (UPDATE: id column is unique):
id version data
----------------------------
1 4 updated 1st
3 3 updated 2nd
4 1 new 4th
And it should produce the following (UPDATE: see how only 1 is updated and 4 is inserted):
id version data
----------------------------
1 4 updated 1st
2 2 second data set
3 5 third data set
4 1 new 4th
I've looked at INSERT ... ON DUPLICATE KEY UPDATE ... statement, but it doesn't allow for some sort of WHERE clause. Also, I can't really use REPLACE because it also does not allow WHERE. Is this even possible with a single MySQL statement?
I am using Java and am trying to possible insert/update many records using the PreparedStatement with batching (addBatch). Any help would be appreciated.
UPDATE: Is there any way to use this query with the PreparedStatement in Java? I have a List of Document objects with id, version, and data.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编辑:在我之前的回答中,我建议对
(id, version)
需要一个唯一的约束,但实际上这是没有必要的。仅对id
的唯一约束就足以使解决方案发挥作用。您应该能够使用
REPLACE
< /a> 命令如下:测试用例:
结果:
作为旁注,为了帮助您了解
REPLACE
命令中发生的情况,请注意以下内容:然后是
IFNULL() 函数负责“覆盖”主表中的最新版本(如果存在),如 id=3、version=5 的情况。因此,如下所示:
上面的结果集仅包含辅助表中的记录,但如果这些记录中的任何一条恰好在主表中具有较新的版本,则该行将被主表中的数据覆盖。这是我们为
REPLACE
命令提供的输入。EDIT: In my earlier answer I suggested that a unique constraint is needed on
(id, version)
, but actually this is not necessary. Your unique constraint onid
only is enough for the solution to work.You should be able to use the
REPLACE
command as follows:Test case:
Result:
As a side-note, to help you understand what's happening in that
REPLACE
command, note the following:Then the
IFNULL()
functions were taking care of "overwriting" the latest version from the main table if one was present, as in the case of id=3, version=5. Therefore the following:The above result set contains only records from the secondary table, but if any of these records happen to have a newer version in the main table, then the row is overwritten by the data from the main table. This is the input that we are feeding the
REPLACE
command.我认为 INSERT ON DUPLICATE KEY UPDATE 是您最好的选择。您可以像未经测试的语法一样使用它
,但我相信这个想法应该可行。
I think INSERT ON DUPLICATE KEY UPDATE is your best bet. You can use it like
Untested syntax, but I belive the idea should work.