Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating rows in jOOQ with joins

Tags:

java

sql

mysql

jooq

I believe joins aren't supported with updates in jOOQ, so I've been exploring how to work around it...

My first attempt was to use where in, but the problem is that MySQL doesn't support target tables in the FROM clause:

create
    .update(USER)
    .set(USER.name, concat(USER.NAME, "some text"))
    .where(USER.ID.in(
        create
            .select(USER.ID)
            .from(USER)
            .join(TEAM)
            .on(USER.TEAM_ID.eq(TEAM.ID))
            .where(TEAM.STATE.equal("test"))
    ))
    .execute();

My second attempt was to use a temporary table for USER (inspired by this answer). The issue is, I can't figure out how to reference a temporary table in the select. Here is my attempt so far using native SQL:

create
    .update(USER)
    .set(USER.name, concat(USER.NAME, "some text"))
    .where(USER.ID.in(
        create
            .select("user_nested.id") // This line doesn't work
            .from("SELECT * FROM user AS user_nested")
            .join(TEAM)
            .on("user_nested.team_id = team.id")
            .where(TEAM.STATE.equal("test"))
    ))
    .execute();

The query I ultimately want to end up with is something like:

UPDATE user
SET user.name = concat(user.email, 'some text')
WHERE user.id IN (
    SELECT user_nested.id
    FROM (SELECT * FROM user) AS user_nested
    JOIN team
    ON user_nested.team_id = team.id
    WHERE team.state = 'test'
);

Is this possible to achieve with jOOQ? If not, perhaps I should use the native SQL code for the whole query.

Edit: I have managed to get this working but it's pretty janky, so I'm still interested in alternative approaches.

Janky working solution:

Field<Long> userId = DSL.field("user_nested.id", Long.class);
create
    .update(USER)
    .set(USER.NAME, (concat(USER.NAME, "some text")))
    .where(USER.ID.in(
        create
            .select(userId)
            .from("(SELECT * FROM user) AS user_nested")
            .join(TEAM)
            .on("user_nested.team_id = team.id")
            .where(TEAM.STATE.equal("test"))
    ))
like image 282
Matthew Fitch Avatar asked Jan 10 '19 14:01

Matthew Fitch


People also ask

Are joins allowed in update statement?

An UPDATE statement can include JOIN operations.

Can we use join in update query in MySQL?

JOIN clause in MySQL is used in the statement to retrieve data by joining multiple tables within a single query. The UPDATE JOIN is a MySQL statement used to perform cross-table updates that means we can update one table using another table with the JOIN clause condition.

How do you create a record in JOOQ?

// Create a new record BookRecord book1 = create. newRecord(BOOK); // Insert the record: INSERT INTO BOOK (TITLE) VALUES ('1984'); book1. setTitle("1984"); book1. store(); // Update the record: UPDATE BOOK SET PUBLISHED_IN = 1984 WHERE ID = [id] book1.


1 Answers

I believe joins aren't supported with updates in jOOQ

You're probably thinking that because there's no UpdateJoinStep type much like there's a SelectJoinStep that using a join with updates is not possible in jOOQ. But beware that SelectJoinStep is mere convenience. The JOIN operator is an operator that connects two tables, not a keyword in SQL. Thus, jOOQ supports it as an operator on the Table type. Using your SQL update as an example:

Field<Long> userId = DSL.field("user_nested.id", Long.class);
create
    .update(USER.join(TEAM).on(TEAM.ID.eq(USER.TEAM_ID)))
    .set(USER.NAME, (concat(USER.NAME, "some text")))
    .where(TEAM.STATE.equal("test"))

You can pass the above table expression to DSLContext.update(Table) like any other. I suspect this obsoletes your remaining question?

like image 118
Lukas Eder Avatar answered Sep 25 '22 13:09

Lukas Eder