【问题标题】:SELECT from result of UPDATE ... RETURNING in jOOQ从更新结果中选择...在 jOOQ 中返回
【发布时间】:2020-11-09 21:38:30
【问题描述】:

我正在将一些旧的 PostgreSQL 代码转换为 jOOQ,我目前正在努力处理具有多个 WITH 子句的 SQL,其中每个子句都依赖于前一个子句。最好保持 SQL 逻辑的编写方式而不是更改它(例如对 DB 的多个查询)。

看起来,例如,没有办法在 UPDATE ... RETURNING 上执行 SELECT

dsl.select(DSL.asterisk())
   .from(dsl.update(...)
            .returning(DSL.asterisk())
   )

我创建了一些测试表,试图创建某种 MVCE:

create table dashboard.test (id int primary key not null, data text); --test table

with updated_test AS (
    UPDATE dashboard.test SET data = 'new data'
    WHERE id = 1
    returning data
),
    test_user AS (
        select du.* from dashboard.dashboard_user du, updated_test -- from previous WITH
        where du.is_active AND du.data = updated_test.data
    )
SELECT jsonb_build_object('test_user', to_jsonb(tu.*), 'updated_test', to_jsonb(ut.*))
FROM test_user tu, updated_test ut; -- from both WITH clauses

到目前为止,这是我的 jOOQ 代码(用 Kotlin 编写):

dsl.with("updated_test").`as`(
                dsl.update(Tables.TEST)
                        .set(Tables.TEST.DATA, DSL.value("new data"))
                        .returning(Tables.TEST.DATA) //ERROR is here: Required Select<*>, found UpdateResultStep<TestRecord>
        ).with("test_user").`as`(
                dsl
                        .select(DSL.asterisk())
                        .from(
                                Tables.DASHBOARD_USER,
                                DSL.table(DSL.name("updated_test")) //or what to use here?
                        )
                        .where(Tables.DASHBOARD_USER.IS_ACTIVE.isTrue
                                .and(Tables.DASHBOARD_USER.DATA.eq(DSL.field(DSL.name("updated_test.data"), String::class.java)))
                        )

        )
                .select() //here goes my own logic for jsonBBuildObject (which is tested and works for other queries)
                .from(
                        DSL.table(DSL.name("updated_test")), //what to use here
                        DSL.table(DSL.name("test_user")) //or here
                )

是否有任何解决方法?如果可能,我想避免更改 SQL。 此外,在这个项目中,这个技巧经常用于从 UPDATE 子句中获取 JSON(B)(表也有 JSON(B) 列):

with _updated AS (update dashboard.test SET data = 'something' WHERE id = 1 returning *)
select to_jsonb(_updated.*) from _updated;

如果没有解决方法,这对我们来说将是一个真正的倒退。

我正在使用 JOOQ 版本 3.13.3 和 Postgres 12.0。

【问题讨论】:

    标签: postgresql jooq


    【解决方案1】:

    jOOQ 目前不支持此功能,请参阅:

    与往常一样,解决方法是,当某些供应商特定的语法不受支持时,求助于plain SQL templating

    例如

    // If you don't need to map data types
    dsl.fetch("with t as ({0}) {1}", update, select);
    
    // If you need to map data types
    dsl.resultQuery("with t as ({0}) {1}", update, select).coerce(select.getSelect()).fetch();
    

    【讨论】:

    • 谢谢卢卡斯的回答。 DSLContext::fetch 解决方法是我需要的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 2014-09-23
    • 2021-02-09
    • 2018-08-11
    • 2021-06-08
    • 2016-07-03
    相关资源
    最近更新 更多