首页 > 解决方案 > 使用 jOOQ 从 Postgres 数组中删除几个元素

问题描述

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

所以我的第一次尝试是:

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 中的错误吗?

标签: postgresqljooq

解决方案


我发现我在上面的代码中混合了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();

推荐阅读