【问题标题】:Fetching a row before execute update/delete在执行更新/删除之前获取一行
【发布时间】:2020-05-25 22:30:09
【问题描述】:

是否可以在更改之前获取已删除或更新的行?

假设我有以下声明

        dslContext.deleteFrom(Tables.USERS)
                .where(Tables.USERS.NAME.eq("xy"))
                .execute();

我想打印与where 语句匹配的所有行。我知道有一个可以使用的DefaultExecuteListener 类,但我不知道该怎么做。

【问题讨论】:

  • 您使用的是什么方言和版本?
  • @LukasEder 版本 3.11.11,mysql

标签: spring-boot jooq


【解决方案1】:

不幸的是,MySQL 还不支持DELETE .. RETURNING 样式语句(见下文)。

适用于所有具有多个往返行程的 RDBMS 的解决方案

适用于各种复杂的DELETEUPDATE 语句的彻底解决方案将使用VisitListener 将语句转换为等效的SELECT 语句。如果您希望它始终正常工作,我可以想到大量必须考虑的边缘情况。

如果“80/20”解决方案足够好,那么您可以使用这个简单的基于正则表达式的ExecuteListener。这是一个例子:

create table t (i int primary key, j int);
insert into t values (1, 1), (2, 2), (3, 3);

然后:

try (Connection c = getConnection()) {
    DSLContext ctx = DSL.using(c);

    ctx.configuration().set(new DefaultExecuteListener() {
        @Override
        public void executeStart(ExecuteContext c) {
            if (c.query() instanceof Delete)
                System.out.println(ctx.fetch(c.sql().replace("delete from", "select * from")));
        }

    });
    System.out.println(ctx.delete(table("t")).where("i > 1").execute());
}

上述程序的输出为:

+----+----+
|   i|   j|
+----+----+
|   2|   2|
|   3|   3|
+----+----+
2

这种方法的缺点可能对您来说可能很重要,也可能无关紧要:

  • 它不适用于普通 SQL 查询。如果这是一个问题,请将instanceof Delete 支票替换为更昂贵的c.sql().startsWith("delete") 支票。
  • 它不考虑区分大小写(例如普通 SQL DELETE 语句)或格式化 SQL。当然,这是可以解决的。
  • 它不适用于某些 MySQL 特定的 DELETE 子句,例如 PARTITIONIGNORE,您也可以修复它们。
  • 该方法假定可以在同一个Connection 上运行第二条语句。根据您的DataSource/事务模型,情况可能并非如此。

适用于某些非 MySQL RDBMS 的解决方案

为了完整起见和此答案的未来读者,我还将提供一个适用于 DB2、Firebird、Oracle、PostgreSQL 和 SQL Server 的解决方案,它们都具有DELETE .. RETURNING 或等效语句的形式。在这些 RDBMS 上,您可以编写:

dslContext.deleteFrom(Tables.USERS)
          .where(Tables.USERS.NAME.eq("xy"))
          .returning()
          .fetch();

这将删除记录并在一个语句中返回所有受影响的记录,而不是创建两个往返。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多