-
Notifications
You must be signed in to change notification settings - Fork 10
UPSERT
Konstantin Triger edited this page Sep 18, 2019
·
8 revisions
UPSERT
stands for UPDATE
or INSERT
in a single operation. In certain cases a record with a same unique key (not necessarily primary!), may already exist in the table. This is where UPSERT
comes to the rescue. SQL:2003 standard defines MERGE clause to handle it, but, unfortunately, not all vendors support it. Yet, the most popular provide some way to perform an UPSERT
.Below are the examples for Oracle, SQL Server, PostgreSQL, MySQL.
Entity used:
@Tuple
@Table(name = "member_topic")
@Data // lombok
public static class MemberTopic {
@Id
private int Member;
@Id
private int topic;
private String notes;
}
Supports
MERGE
MemberTopic newTopic = ... // external parameter
FluentQuery query = FluentJPA.SQL((MemberTopic target) -> {
// view is used for INSERT and alias
View<MemberTopic> targetView = viewOf(target, MemberTopic::getMember,
MemberTopic::getTopic,
MemberTopic::getNotes);
// source is a sub query
MemberTopic source = subQuery(() -> {
// select and alias values in the view order
SELECT(targetView.fromAliased(newTopic));
FROM(DUAL()); // The Oracle way
});
// match new record with existing
MERGE().INTO(target).USING(source)
// matching criteria
.ON(target.getMember() == source.getMember()
&& target.getTopic() == source.getTopic());
WHEN_MATCHED().THEN(() -> {
MERGE_UPDATE().SET(() -> {
// just update the notes
target.setNotes(source.getNotes());
});
});
// perform the INSERT
WHEN_NOT_MATCHED().THEN(MERGE_INSERT(targetView.columnNames(),
VALUES(targetView.from(source))));
});
query.createQuery(em).executeUpdate();
Supports
MERGE
MemberTopic newTopic = ... // external parameter
FluentQuery query = FluentJPA.SQL((MemberTopic target) -> {
// view is used for INSERT and alias
View<MemberTopic> targetView = viewOf(target, MemberTopic::getMember,
MemberTopic::getTopic,
MemberTopic::getNotes);
// source is a sub query
MemberTopic source = subQuery(() -> {
// select and alias values in the view order
SELECT(targetView.fromAliased(newTopic));
});
// match new record with existing
MERGE().INTO(target).USING(source)
// matching criteria
.ON(target.getMember() == source.getMember()
&& target.getTopic() == source.getTopic());
WHEN_MATCHED().THEN(() -> {
MERGE_UPDATE().SET(() -> {
// just update the notes
target.setNotes(source.getNotes());
});
});
// perform the INSERT
WHEN_NOT_MATCHED().THEN(MERGE_INSERT(targetView.columnNames(),
VALUES(targetView.from(source))));
});
query.createQuery(em).executeUpdate();
No
MERGE
support
int newMember = 0;
int newTopic 110;
String newNotes = "test";
FluentQuery query = FluentJPA.SQL((MemberTopic target) -> {
INSERT().INTO(target);
VALUES(row(newMember, newTopic, newNotes));
ON_DUPLICATE_KEY_UPDATE(() -> {
target.setNotes(newNotes);
});
});
query.createQuery(em).executeUpdate();
No
MERGE
support
int newMember = 0;
int newTopic 110;
String newNotes = "test";
FluentQuery query = FluentJPA.SQL((MemberTopic target) -> {
INSERT().INTO(target);
VALUES(row(newMember, newTopic, newNotes));
ON_CONFLICT(MemberTopic::getMember, MemberTopic::getTopic).DO_UPDATE().SET(() -> {
target.setNotes(newNotes);
});
});
query.createQuery(em).executeUpdate();
Getting Started
- Introduction
- Setup
- Data Types
- Entities & Tuples
- Sub Queries
- JPA Integration
- Java Language Support
- Directives
- Library
- Returning Results
- JPA Repositories
Examples
Basic SQL DML Statements
Advanced SQL DML Statements
- Common Table Expressions (WITH Clause)
- Window Functions (OVER Clause)
- Aggregate Expressions
- MERGE
- Temporal Tables
Advanced Topics