【问题标题】:Remove several elements from Postgres array with jOOQ使用 jOOQ 从 Postgres 数组中删除几个元素
【发布时间】:2018-10-14 01:37:30
【问题描述】:

我正在尝试使用 jOOQ 创建类似于 arrayRemove 的函数,但这允许从 uuid[] 类型的 PostgreSQL 列中一次删除多个元素。

所以我的第一次尝试是:

private Field<UUID[]> arrayRemoveAll(final Field<UUID[]> field, final Set<UUID> elements) {
    return select(field("array_agg(tab.col)", UUID[].class))
            .from(unnest(field).as("tab", "col"))
            .where(field("tab.col", UUID.class).notIn(elements))
            .asField();
}

它成功删除了每个请求的元素,但如果我尝试删除每个元素,则会返回 null 而不是空数组。

所以我在我的代码中添加了一个合并,让它返回一个空数组:

private Field<UUID[]> arrayRemoveAll(final Field<UUID[]> field, final Set<UUID> elements) {
    final Field<UUID[]> newArray = select(field("array_agg(tab.col)", UUID[].class))
            .from(unnest(field).as("tab", "col"))
            .where(field("tab.col", UUID.class).notIn(elements))
            .asField();
    return coalesce(newArray, field("{}", UUID[].class));
}

但是运行这段代码会抛出这个异常:

org.jooq.exception.DataAccessException: SQL [<<confidential SQL removed>>]
    Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"

这是它所抱怨的 SQL 异常的一部分(注意coalesce 中的尾随逗号和缺少第二个参数):

coalesce((select array_agg(tab.col)
          from unnest("my_schema"."my_table"."my_field") as "tab"("col")
          where tab.col not in (?, ?)), )

这是 jOOQ 中的错误吗?

【问题讨论】:

    标签: postgresql jooq


    【解决方案1】:

    我发现我在上面的代码中混合了fieldval,将field("{}", UUID[].class) 更改为val(new UUID[0]) 可以解决问题。

    还可以查看 Lukas Eder 关于如何使用 field 解决问题的答案。

    因此,带有泛型的最终代码如下所示:

    private <T> Field<T[]> arrayRemoveAll(final Field<T[]> field, final Set<T> elements, final T[] emptyArray) {
        final Field<T[]> newArray = select(field("array_agg(tab.col)"))
                .from(unnest(field).as("tab", "col"))
                .where(field("tab.col").notIn(elements))
                .asField();
        return coalesce(newArray, val(emptyArray));
    }
    

    你可以像这样在你的语句中使用它:

    using(configuration)
        .update(MY_TABLE)
        .set(MY_TABLE.MY_COLUMN,
             arrayRemoveAll(MY_TABLE.MY_COLUMN, someElements, new UUID[0]))
        .where(MY_TABLE.ID.eq(...))
        .execute();
    

    【讨论】:

    • 仍然不确定使用field是否应该让jOOQ生成无效的SQL,但至少现在我有一个可行的解决方案。
    【解决方案2】:

    您的 field("{}") 不会在 SQL 中生成 {} 字符串,但被认为是 jOOQ 的普通 SQL 模板语言的一部分,遗憾的是它不允许转义这些大括号: https://www.jooq.org/doc/latest/manual/sql-building/plain-sql-templating

    幸运的是,PostgreSQL 支持一种更正式、符合标准的方式来创建空数组字面量:

    field("array[]::uuid[]", UUID.class)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-12
      • 1970-01-01
      • 2019-01-26
      • 2014-04-21
      • 1970-01-01
      • 2011-10-31
      • 1970-01-01
      相关资源
      最近更新 更多