Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use MERGE INTO to simulate "upsert" in Apache Derby?

We're using Derby and have a lot of code which goes like this:

try (ResultSet rs = executeQuery(...)) {
    if (rs.next()) {
        updateRowSet(rs, ...);
        rs.updateRow();
    } else {
        executeUpdate(...);
    }
}

In the past, we were searching for a way to do this logic server-side, and found that some databases supported an "upsert" (update or insert) operation. Derby had a feature request for MERGE INTO which was supposedly the SQL:2003 standard way of doing this, so we sat and watched the ticket, and much time passed.

Derby 10.11 finally added MERGE INTO. Nobody has had time to go through and update the code to use it yet, but on reading their documentation, all their examples show merging from one table to another. But hang on, our data isn't in a table yet!

I know I could put it in a table, but then it is multiple queries again, which completely defeats the point of using it.

I'm sure it is possible to do it without putting it into a table, but because the documentation does not show a single example, I'm not sure how to proceed.

Here is what I have been trying:

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();
}

This doesn't appear to do any of the inserts, but also doesn't give an error, so I have absolutely nothing to go on.

like image 753
Hakanai Avatar asked Jan 12 '16 02:01

Hakanai


People also ask

Is Upsert and merge same?

A relational database management system uses SQL MERGE (also called upsert) statements to INSERT new records or UPDATE existing records depending on whether condition matches. It was officially introduced in the SQL:2003 standard, and expanded in the SQL:2008 standard.

How do I connect to Derby database in eclipse?

Choose Window > Preferences from the menu to open the Eclipse Preferences dialog. Navigate to Connectivity > Driver Definitions. Select the Derby 10.2 folder and click Add.... In the New Driver Definition dialog, select Derby Client JDBC Driver and click OK.

How do I open Apache Derby database?

If you want to connect to a Derby database which is running in server mode then you can use the following command. connect 'jdbc:derby://localhost:1527/c:\temp\db\FAQ\db;create=true';


1 Answers

Sharing it for all sad people that still use derby :) So I solved it with help of merge into statement( https://db.apache.org/derby/docs/10.14/ref/rrefsqljmerge.html) in that way:

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')

Where foo is the table where u want to upsert row and SYSIBM.SYSDUMMY1 derby dummy table that has only 1 useless row (btw it doesn't work with one of my regular table that has multiple rows)

As u might understand it's more like workaround but better than nothing to achive upsert aim.

like image 75
Dzmitry Hubin Avatar answered Oct 24 '22 23:10

Dzmitry Hubin