更新内的子查询以设置多个值
Subquery inside an update to set multiple values
我想使用 update().set()
移动记录的 DateTime。当我尝试 given example in the jOOQ docs for using a subselect 时,我发现我需要转换为 Row2
类型,因为我想设置两个变量。有了这个,查询就会以一种不寻常的方式构建 (或者至少不是根据我对 jOOQ 文档中给出示例的查询的期望):
public static void moveEventStart(final LocalDate previousEventStart, final LocalDate newEventStart) {
final Days changeInterval = Days.daysBetween(previousEventStart, newEventStart);
ActivityTbl a = ACTIVITY.as("a");
ActivityTbl a2 = ACTIVITY.as("a2")
jooq()
.update(a)
.set(
(Row2) row(a.START, a.END),
select(
models.Jooq.dateAdd(a2.START, changeInterval.getDays(), DatePart.DAY),
models.Jooq.dateAdd(a2.END, changeInterval.getDays(), DatePart.DAY))
.from(a2)
.where(...))
.where(...)
.execute();
}
dateAdd 函数是这样构建的:
public static Field<Date> dateAdd(TableField<?, LocalDateTime> field, int interval, DatePart datePart) {
String unit;
switch (datePart) {
case YEAR:
unit = "YEAR";
break;
case MONTH:
unit = "MONTH";
break;
case DAY:
unit = "DAY";
break;
case HOUR:
unit = "HOUR";
break;
case MINUTE:
unit = "MINUTE";
break;
case SECOND:
unit = "SECOND";
break;
default:
unit = "";
}
return DSL.field(
"DATE_ADD({0}, INTERVAL {1} " + unit + ")", SQLDataType.DATE, field, DSL.inline(interval));
}
产生:
update `Activity` as `a`
set(`start`, `end`) = (
select * from (
select
DATE_ADD(`a2`.`start`, INTERVAL 1 DAY),
DATE_ADD(`a2`.`end`, INTERVAL 1 DAY)
from `Activity` as `a2`
where (...) as `t`
)
where (...)
为什么 jOOQ 在已经给定的 select
之上构建一个 select
?我该如何进行这项工作,以便它根据给定的 select?
设置多个值
MySQL
不支持语法
MySQL 尚不支持此语法。您可以在 jOOQ 的 UpdateSetFirstStep.set(Row2, Select)
方法的 Javadoc 上看到,它列出了这些支持的方言:
@Support({ASE,AURORA_POSTGRES,BIGQUERY,COCKROACHDB,DB2,H2,HANA,HSQLDB,INGRES,ORACLE,POSTGRES,SNOWFLAKE,SQLSERVER,SYBASE})
jOOQ 可以模拟语法:
- https://github.com/jOOQ/jOOQ/issues/10522(对不相关的子查询使用
UPDATE .. FROM
)
- https://github.com/jOOQ/jOOQ/issues/10523(通过将相关子查询拆分为两个)
从 jOOQ 3.15 开始,这两种仿真都不可用
如果支持语法,为什么要额外派生 table?
如果支持该语法,那么额外派生的 table 是 jOOQ 针对 MySQL 中的限制实施的解决方法,其中 UPDATE
或 DELETE
查询不能从相关子查询中引用 DML 语句的目标 table(但神奇的是,当在派生 table 中嵌套相关子查询一级时,此限制消失了)。参见:
- https://github.com/jOOQ/jOOQ/issues/6583
- https://dev.mysql.com/doc/refman/8.0/en/subquery-restrictions.html
- MySQL rationale behind "Can't specify target table for update in FROM clause"
我想使用 update().set()
移动记录的 DateTime。当我尝试 given example in the jOOQ docs for using a subselect 时,我发现我需要转换为 Row2
类型,因为我想设置两个变量。有了这个,查询就会以一种不寻常的方式构建 (或者至少不是根据我对 jOOQ 文档中给出示例的查询的期望):
public static void moveEventStart(final LocalDate previousEventStart, final LocalDate newEventStart) {
final Days changeInterval = Days.daysBetween(previousEventStart, newEventStart);
ActivityTbl a = ACTIVITY.as("a");
ActivityTbl a2 = ACTIVITY.as("a2")
jooq()
.update(a)
.set(
(Row2) row(a.START, a.END),
select(
models.Jooq.dateAdd(a2.START, changeInterval.getDays(), DatePart.DAY),
models.Jooq.dateAdd(a2.END, changeInterval.getDays(), DatePart.DAY))
.from(a2)
.where(...))
.where(...)
.execute();
}
dateAdd 函数是这样构建的:
public static Field<Date> dateAdd(TableField<?, LocalDateTime> field, int interval, DatePart datePart) {
String unit;
switch (datePart) {
case YEAR:
unit = "YEAR";
break;
case MONTH:
unit = "MONTH";
break;
case DAY:
unit = "DAY";
break;
case HOUR:
unit = "HOUR";
break;
case MINUTE:
unit = "MINUTE";
break;
case SECOND:
unit = "SECOND";
break;
default:
unit = "";
}
return DSL.field(
"DATE_ADD({0}, INTERVAL {1} " + unit + ")", SQLDataType.DATE, field, DSL.inline(interval));
}
产生:
update `Activity` as `a`
set(`start`, `end`) = (
select * from (
select
DATE_ADD(`a2`.`start`, INTERVAL 1 DAY),
DATE_ADD(`a2`.`end`, INTERVAL 1 DAY)
from `Activity` as `a2`
where (...) as `t`
)
where (...)
为什么 jOOQ 在已经给定的 select
之上构建一个 select
?我该如何进行这项工作,以便它根据给定的 select?
MySQL
不支持语法MySQL 尚不支持此语法。您可以在 jOOQ 的 UpdateSetFirstStep.set(Row2, Select)
方法的 Javadoc 上看到,它列出了这些支持的方言:
@Support({ASE,AURORA_POSTGRES,BIGQUERY,COCKROACHDB,DB2,H2,HANA,HSQLDB,INGRES,ORACLE,POSTGRES,SNOWFLAKE,SQLSERVER,SYBASE})
jOOQ 可以模拟语法:
- https://github.com/jOOQ/jOOQ/issues/10522(对不相关的子查询使用
UPDATE .. FROM
) - https://github.com/jOOQ/jOOQ/issues/10523(通过将相关子查询拆分为两个)
从 jOOQ 3.15 开始,这两种仿真都不可用
如果支持语法,为什么要额外派生 table?
如果支持该语法,那么额外派生的 table 是 jOOQ 针对 MySQL 中的限制实施的解决方法,其中 UPDATE
或 DELETE
查询不能从相关子查询中引用 DML 语句的目标 table(但神奇的是,当在派生 table 中嵌套相关子查询一级时,此限制消失了)。参见:
- https://github.com/jOOQ/jOOQ/issues/6583
- https://dev.mysql.com/doc/refman/8.0/en/subquery-restrictions.html
- MySQL rationale behind "Can't specify target table for update in FROM clause"