我们正在使用Derby,并且有很多代码是这样的:
try (ResultSet rs = executeQuery(...)) {
if (rs.next()) {
updateRowSet(rs, ...);
rs.updateRow();
} else {
executeUpdate(...);
}
}
过去,我们正在寻找一种在逻辑服务器端执行此操作的方法,并发现某些数据库支持"upsert"(更新或插入(操作。Derby有一个功能请求MERGE INTO
据说是SQL:2003的标准方法,所以我们坐下来看票,很多时间过去了。
德比10.11终于加MERGE INTO
.没有人有时间浏览和更新代码以使用它,但是在阅读他们的文档时,他们所有的示例都显示从一个表合并到另一个表。但是等等,我们的数据还没有在表格中!
我知道我可以把它放在一个表中,但随后又是多个查询,这完全违背了使用它的意义。
我确信可以在不将其放入表中的情况下做到这一点,但是由于文档没有显示单个示例,因此我不确定如何继续。
这是我一直在尝试的:
try (PreparedStatement ps = connection.prepareStatement(
"MERGE INTO things AS target " +
// Awkward point 1:
// It wants a "source" table, but I don't have one.
// So I thought I would try to use the same table with
// another name.
" USING things AS source ON target.id = ?" +
" WHEN MATCHED THEN" +
" UPDATE SET data = ?" +
" WHEN NOT MATCHED THEN" +
" INSERT (id, data) VALUES (??, ?)"))
{
ps.setLong(1, id);
ps.setBinaryStream(2, data);
ps.setLong(3, id);
// Awkward point 2:
// Passing an InputStream into a query as two
// parameters.
ps.setBinaryStream(4, data);
ps.execute();
}
这似乎没有做任何插入,但也不会给出错误,所以我绝对没有什么可继续的。
分享给所有仍然使用德比:)的悲伤的人所以我在merge into statement
(https://db.apache.org/derby/docs/10.14/ref/rrefsqljmerge.html(的帮助下以这种方式解决了它:
MERGE INTO foo
USING SYSIBM.SYSDUMMY1
ON foo.id = '1' AND foo.language = 'en'
WHEN MATCHED THEN
UPDATE SET name = 'name2', image = 'someImgUrl2'
WHEN NOT MATCHED THEN
INSERT (id, name, language, image)
VALUES ('1', 'name1', 'en', 'someImgUrl1')
其中foo是您要更新插入行的表,并且只有1 SYSIBM.SYSDUMMY1
无用行的derby虚拟表(顺便说一句,它不适用于具有多行的常规表之一(
正如您可能理解的那样,这更像是解决方法,但实现更新插入目标总比没有好。
以下内容适用于我 Apache Derby 10.12.1.1:
merge into FOO
using RANDOM_TABLE
on FOO.guid = 'qwerty'
when matched then
update set guid = 'qwerty'
when not matched then
insert (guid) values('qwerty')
在这里,FOO是我的目标表,要进行更新插入,RANDOM_TABLE是我数据库中的任何其他表。值"qwerty"是我的数据和唯一键。在此示例中,FOO 只有一列,但它应该分别向插入和更新添加更多列。
我发现这种语法非常不优雅,但至少它似乎确实避免执行两个单独的语句来完成这项工作。