我可以使用 MERGE INTO 在 Apache Derby 中模拟"upsert"吗?



我们正在使用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 只有一列,但它应该分别向插入和更新添加更多列。

我发现这种语法非常不优雅,但至少它似乎确实避免执行两个单独的语句来完成这项工作。

最新更新