我在Oracle 11g springboot 環境中運行 jOOQ 3.13.6。
要使用 listagg 函式,我正在嘗試此處提供的解決方案:https ://stackoverflow.com/a/69482329/17505774
示例代碼:
@Autowired
private DSLContext dsl;
// setting tables
Table table1 = DSL.table("table_1").as("t1");
Table table2 = DSL.table("table_2").as("t2");
// creating fields
final List<Field<?>> fields = new ArrayList<Field<?>>();
fields.add(DSL.field(DSL.name("t1", "t1_id")).as("id"));
Field cf = DSL.field(DSL.name("t2", "t2_code")).as("code");
fields.add(listAgg(cf, ";", null)); // no order
// running query
dsl.settings().withRenderQuotedNames(RenderQuotedNames.EXPLICIT_DEFAULT_UNQUOTED);
dsl.select(fields)
.from(table1)
.join(table2).on("t1.t1_id = t2.t1_id")
.where("t1.t1_id = ?", id)
.groupBy(fields)
但是,它執行以下查詢:
select t1.t1_id id,
listagg(t2.t2_code) within group (null) as code
from table_1 t1
join table_2 t2 on ( t1.t1_id = t2.t2_id )
where t1.t1_id = 1
group by id
group by應該使用原始列名 (t1.t1_id),而不是別名。
uj5u.com熱心網友回復:
請注意,為了這個答案,并且為了簡潔起見,我假設您一直在使用code generator。如果不使用代碼生成,答案是一樣的。
為什么現在的行為?
在 jOOQ 中,一個別名列運算式T1.T1_ID.as("id")只能生成其自身的 2 個不同版本:
T1.T1_ID as ID, 即別名宣告(當在SELECT頂層時)ID,即別名參考(當在子句之外的任何其他子句/運算式內時SELECT)
沒有第三種型別的生成 SQL 取決于您嵌入別名運算式的位置,例如,T1.T1_ID當您將運算式放入WHEREor時的非別名列運算式GROUP BY等。基本原理很簡單。用戶在撰寫時會期望什么:
groupBy(T1.T1_ID.as("id"))
為什么他們會期望as()呼叫是無操作的?這將比現狀更令人驚訝。
與其他渲染模式的一致性
jOOQ中還有其他型別QueryPart,它們具有類似的別名功能:
FieldTableWindowSpecificationParameterCTE
讓我們看一下 CTE 示例:
Table<?> cte = name("cte").as(select(...))
該cte參考有 2 種將自身呈現給 SQL 的模式:
- CTE 宣告(如果放在
WITH子句中) - CTE 參考(如果放在
FROM等中)
我認為您不會期望該cte參考永遠忽略別名,而只是渲染其SELECT本身?
與表別名類似:
T1 x = T1.as("x");
這可以將自己呈現為:
- 別名宣告(如果放在
FROM子句中) - 別名參考
因為該FROM子句在邏輯上在任何其他子句之前,所以您永遠不會期望您的x參考僅呈現T1,而不是xor T1 as x,對嗎?
因此,出于整個 jOOQ API 的一致性原因,Field別名的行為也必須與所有其他別名一樣。
該怎么做?
不要在SELECT子句之外重復使用別名運算式。完全按照您撰寫實際 SQL 的方式撰寫 jOOQ SQL:
ctx.select(T1.T1_ID.as("id"), ...)
.from(T1)
.groupBy(T1.T1_ID)
...
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/439932.html
