从jOOQ 3.17开始, [Condition](https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/Condition.html)类型扩展了 [Field<Boolean>](https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/Field.html)类型。因为,这就是SQL标准所认为的,在种类上:
<boolean value expression> ::=
<predicate>
确切的定义包含中间规则,但你会明白这个意思。一个<predicate> (在jOOQ中是一个 [Condition](https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/Condition.html)在jOOQ中是一个<boolean value expression> ,可以在任何可以使用 的地方使用,这也可以在投影、谓词和其他地方使用。
不是所有的SQL方言都是这样工作的,事实上,在SQL:1999对BOOLEAN 数据类型进行标准化之前,SQL本身并不是这样工作的。例如,SQL-92将<predicate> 列为可能的替代品,只用于<search condition> ,例如用于<where clause> ,但不用于任何普通的<value expression> 。
因此,虽然这在PostgreSQL中是有效的,它支持标准的SQLBOOLEAN 类型:
SELECT id, id > 2 AS big_id
FROM book
ORDER BY id
编制:
|id |big_id|
|---|------|
|1 |false |
|2 |false |
|3 |true |
|4 |true |
它在Oracle中不起作用,例如,它用通常有用的错误信息来取悦我们。
SQL错误[923] [42000]。ORA-00923:在预期的地方没有找到FROM关键字
这在jOOQ 3.16或更低版本中是如何工作的
jOOQ一直支持交换使用Condition 和Field<Boolean> 的方法。这里有两个封装方法。
DSL.field(Condition)返回Field<Boolean>DSL.condition(Field<Boolean>)返回Condition
这在这里有记载。因此,前面的查询可以写成下面的样子:
Result<Record2<Integer, Boolean>> result =
ctx.select(BOOK.ID, field(BOOK.ID.gt(2)).as("big_id"))
// ^^^^^^^^^^^^^^^^^^^^ wrapping condition with field()
.from(BOOK)
.orderBy(BOOK.ID)
.fetch();
生成的SQL看起来是这样的,对于PostgreSQL:
SELECT
book.id,
(book.id > 2) AS big_id
FROM book
ORDER BY book.id
而对于Oracle来说,这是对该功能的模拟。
SELECT
book.id,
CASE
WHEN book.id > 2 THEN 1
WHEN NOT (book.id > 2) THEN 0
END big_id
FROM book
ORDER BY book.id
NULL 这个模拟保留了我们所喜爱的三值逻辑,即在BOOLEAN 的情况下,BOOK.ID 是NULL 。
这在jOOQ 3.17中是如何工作的,现在
从jOOQ 3.17和#11969开始,不再需要对field(Condition) 进行手动包装,你可以直接投射Condition 。
Result<Record2<Integer, Boolean>> result =
ctx.select(BOOK.ID, BOOK.ID.gt(2).as("big_id"))
// ^^^^^^^^^^^^^ no more wrapping necessary
.from(BOOK)
.orderBy(BOOK.ID)
.fetch();
其行为与你包装了条件(包括结果类型)的情况完全相同,而且对于Oracle和其他不支持BOOLEAN 值表达式的方言来说,模拟仍然起作用。这意味着你也可以在其他接受Field 类型的子句中使用Condition ,包括,例如:
GROUP BY或PARTITION BYORDER BY