构建涉及可选限制的动态 SQL 的最佳方法?

问题描述 投票:0回答:2

在 JOOQ 中选择性地将 LIMIT 应用于查询的最佳方法是什么?我想跑步:

SelectSeekStepN<Record> readyToFetch = dslContext.select(selectFields).
    from(derivedTable).
    where(conditions).
    orderBy(orderForward);
if (length != Integer.MAX_VALUE)
    readyToFetch = readyToFetch.limit(length);

limit()
返回
SelectLimitPercentStep<Record>
,它不是
SelectSeekStepN<Record>
的子类,因此我收到编译器错误。

另一方面,如果我将

readyToFetch
的返回类型从
SelectSeekStepN<Record>
更改为与
Select<Record>
的返回类型兼容的
limit()
,那么我无法在
limit()
上调用
Select<Record>
。我需要明确地将其转换为
SelectSeekStepN<Record>

有更好的方法吗?

也许JOOQ应该将

Integer.MAX_VALUE
视为特殊值(无限制),以使这种代码更容易编写...

jooq
2个回答
3
投票

提供无操作来传递给像
LIMIT

这样的子句

可以使用

Field
创建虚拟
DSL.noField(DataType)
表达式,例如,如此处记录的

 dslContext.select(selectFields).
    from(derivedTable).
    where(conditions).
    orderBy(orderForward).
    limit(length != Integer.MAX_VALUE ? length : noField(INTEGER)).
    fetch();

使用动态 SQL 获取正确的类型

您自己的问题已经包含解决方案。这只是一个小打字问题。您可能选择将中间步骤分配给

SelectSeekStepN
,因为您的 IDE 建议使用这种类型。但您可以使用任何超级类型。

Select<Record> readyToFetch;
SelectLimitStep<Record> readyToLimit;

readyToFetch = readyToLimit = dslContext.select(selectFields).
    from(derivedTable).
    where(conditions).
    orderBy(orderForward);
if (length != Integer.MAX_VALUE)
    readyToFetch = readyToLimit.limit(length);
readyToFetch.fetch();

您可以从

ParserImpl
逻辑中获得一些灵感。它到处都这样做。赋值表达式是一件幸事!

在条件表达式上使用类型推断的替代方法:

SelectLimitStep<Record> limit = dslContext.select(selectFields).
    from(derivedTable).
    where(conditions).
    orderBy(orderForward);

Result<?> result = (length != Integer.MAX_VALUE ? limit.limit(length) : limit).fetch();

使用
null
作为明确指示不存在
LIMIT

的方式

使用

null
来表示缺少
LIMIT
是一个非常糟糕的主意,至少有 3 个原因:

  • 大多数 jOOQ API 将
    (Field<?>) null
    解释为
    NULL
    绑定值或
    NULL
    文字,从不解释为不存在的值。如果我们突然只在
    null
     中使用 
    LIMIT
  • 来达到此目的,那将是非常令人惊讶的
  • 即使我们这样做了,我们也必须开始区分
    null
    (缺失值的内部解释)和
    null
    (您作为用户通过 显式向 jOOQ 提供的值)。因此,无论如何,我们在内部都需要一些
    noLimit()
    对象来进行区分,在这种情况下,为什么不将其公开为 API,而不是让你随意修改呢?
  • 某些方言支持
    NULL
    限制。 PostgreSQL 将其解释为不存在的
    LIMIT
    (我觉得这很令人困惑,
    LIMIT
    是“未知”)。 Oracle 将其解释为
    LIMIT 0
    ,这要合理得多。其他方言(例如 MySQL)将
    LIMIT NULL
    视为错误语法而拒绝,这也是合理的。您建议 jOOQ 覆盖此行为并巧妙地重新解释它。我宁愿不!

0
投票

我深入研究了实现,发现还有另一种方法

limit(Number)
null
值视为没有限制。因此,代码可以写成:

Select<Record> readyToFetch = dslContext.select(selectFields).
    from(derivedTable).
    where(conditions).
    orderBy(orderForward).
    limit(length == Integer.MAX_VALUE ? null : length);
© www.soinside.com 2019 - 2024. All rights reserved.