首页 > 解决方案 > 更新内的子查询以设置多个值

问题描述

我想通过使用来移动记录的 DateTime update().set()。当我在 jOOQ 文档中尝试使用子选择的给定示例时,我发现我需要转换为一个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?我该如何进行这项工作,以便根据给定的选择设置多个值?

标签: javasqljooq

解决方案


MySQL 不支持该语法

MySQL 还不支持这种语法。您可以在 jOOQ 方法的 Javadoc 中看到UpdateSetFirstStep.set(Row2, Select),其中列出了支持的这些方言:

@Support({ASE,AURORA_POSTGRES,BIGQUERY,COCKROACHDB,DB2,H2,HANA,HSQLDB,INGRES,ORACLE,POSTGRES,SNOWFLAKE,SQLSERVER,SYBASE})

jOOQ 可以模拟以下语法:

从 jOOQ 3.15 起,这两种仿真都不可用

如果支持语法,为什么要额外派生表?

如果支持该语法,则附加派生表是 jOOQ 为 MySQL 中的限制实现的一种解决方法,其中UPDATEorDELETE查询无法从相关子查询中引用 DML 语句的目标表(但神奇的是,嵌套相关子查询时,此限制消失了子查询派生表中的一级)。看:


推荐阅读