You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL执行DELETE语句后如何获取已删除记录的主键ID?

问题根因
  1. JDBC的getGeneratedKeys()默认仅支持INSERT操作返回自增主键,DELETE操作不会默认填充该结果集。
  2. PostgreSQL需要在DELETE语句后添加RETURNING子句才能显式返回被删除行的指定字段。
  3. 你创建PreparedStatement时未指定需要返回的键字段,即使加了RETURNING也无法正常获取结果。
代码调整步骤

1. 修改删除表单的SQL语句

添加RETURNING id子句,指定删除后返回表单ID:

private static final String REMOVE_FORM = "DELETE FROM forms WHERE name = ? RETURNING id";

2. 调整PreparedStatement初始化逻辑

创建Statement时指定需要返回的ID列,确保返回结果可以被正常获取:

public boolean connect() throws SQLException{
    this.connection = DriverManager.getConnection(URL);
    // 指定返回id列,也可以用Statement.RETURN_GENERATED_KEYS参数替代列名数组
    this.removeFormQuery = this.connection.prepareStatement(REMOVE_FORM, new String[]{"id"});
}

如果后续删除字段、删除字段值的逻辑也需要获取被删ID,对应SQL和PreparedStatement初始化也需要按照上面的逻辑同步修改

3. 调整删除逻辑,修正结果判断的问题

你原有逻辑中用execute()的返回值判断执行结果容易出错,推荐用executeQuery()直接获取删除返回的ID集,用executeUpdate()的返回影响行数判断执行是否成功:

private void removeForm(String form) {
    try {
        removeFormQuery.setString(1, form);
        // 直接执行查询获取被删表单的ID
        ResultSet deletedFormIds = removeFormQuery.executeQuery();
        while (deletedFormIds.next()) {
            int formId = deletedFormIds.getInt("id");
            removeFieldQuery.setInt(1, formId);
            int fieldAffected = removeFieldQuery.executeUpdate();
            if (fieldAffected <= 0) {
                System.out.println("remove field failed");
                continue;
            }
            System.out.println("remove field success");
            ResultSet deletedFieldIds = removeFieldQuery.getGeneratedKeys();
            while (deletedFieldIds.next()) {
                int fieldId = deletedFieldIds.getInt("id");
                removeListItemQuery.setInt(1, fieldId);
                int itemAffected = removeListItemQuery.executeUpdate();
                System.out.println(itemAffected > 0 ? "remove listItem success" : "remove listItem failed");
            }
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
更优方案(推荐)

不需要在代码中循环关联删除,直接在数据库层配置外键级联删除即可:

  • 给第二张表的form_id字段添加外键关联forms.id,设置ON DELETE CASCADE
  • 给第三张表的field_id字段添加外键关联第二张表的主键,设置ON DELETE CASCADE
    配置完成后,只要删除forms表的对应记录,数据库会自动删除所有关联的字段和字段值数据,无需额外的Java代码,执行效率更高也不会出现关联遗漏问题。

内容的提问来源于stack exchange,提问作者Leboroz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:18:02