我正在使用Jooq并尝试在同一个表中生成数据集的近似副本。在此过程中,我想将一个字段的值更新为已知值。我一直在看文档&尝试没有运气的变化。这是我更新REGISTRATION表并将'stage'字段设置为值6(它为5)的方法。所以我最终会得到原始数据加上一个只有不同阶段值的重复集。 在伪代码中
insert into Registration (select * from Registration where stage=5) set stage=6
我在下面尝试了这段代码,并认为我可以添加一个“.set(...)”方法来设置值,但这似乎没有效果。
create.insertInto(REGISTRATION)
.select(
(selectFrom(REGISTRATION)
.where(REGISTRATION.STAGE.eq(5))
)
).execute();
答案 0 :(得分:3)
我不知道支持INSERT .. SELECT .. SET
语法的数据库,如果有这样的语法,它肯定不符合SQL标准。这里的前进方向是写:
INSERT INTO registration (col1, col2, col3, stage, col4, col5)
SELECT col1, col2, col3, 6, col4, col5
FROM registration
WHERE stage = 5;
create.insertInto(REGISTRATION)
.columns(
REGISTRATION.COL1,
REGISTRATION.COL2,
REGISTRATION.COL3,
REGISTRATION.STAGE,
REGISTRATION.COL4,
REGISTRATION.COL5)
.select(
select(
REGISTRATION.COL1,
REGISTRATION.COL2,
REGISTRATION.COL3,
val(6),
REGISTRATION.COL4,
REGISTRATION.COL5)
.from(REGISTRATION)
.where(REGISTRATION.STAGE.eq(5)))
.execute();
隐含以下静态导入:
import static org.jooq.impl.DSL.*;
由于您正在寻找动态SQL解决方案,以下是如何做到这一点:
static <T> int copy(
DSLContext create, Table<?> table, Field<T> field,
T oldValue, T newValue
) {
List<Field<?>> into = new ArrayList<>();
List<Field<?>> from = new ArrayList<>();
into.addAll(Stream.of(table.fields())
.filter(f -> !field.equals(f))
.collect(toList()));
from.addAll(into);
into.add(field);
from.add(val(newValue));
return
create.insertInto(table)
.columns(into)
.select(
select(from)
.from(table)
.where(field.eq(oldValue))
.execute();
}
答案 1 :(得分:2)
感谢Lukas的答案,我将使用一个版本,因为它很好而且一般。我刚才开始工作的答案不那么普遍,但对于其他人来说这可能是一个有用的参考,特别是因为它考虑了身份字段“id”,否则会导致问题。
public void duplicate(int baseStage, int newStage) {
Field<?>[] allFieldsExceptId = Stream.of(REGISTRATION.fields())
.filter(field -> !field.getName().equals("id"))
.toArray(Field[]::new);
Field<?>[] newFields = Stream.of(allFieldsExceptId).map(field -> {
if (field.getName().contentEquals("stage")) {
return val(newStage);
} else {
return field;
}
}).toArray(Field[]::new);
create.insertInto(REGISTRATION)
.columns(allFieldsExceptId)
.select(
select(newFields)
.from(REGISTRATION)
.where(REGISTRATION.STAGE.eq(baseStage)))
.execute();
}