You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

存在外键约束时,如何删除MySQL表中的行?附报错及代码求助

解决MySQL外键约束下的行删除问题

你碰到的这个错误核心原因很明确:外键约束阻止了你直接删除父表记录。因为prodstock表的item_code字段是关联prodlistid的外键,而且外键规则设置的是ON DELETE NO ACTION——这就意味着,只要prodstock里还存在关联这条父记录的子数据,数据库就会拒绝你删除父表的操作。

下面给你几种可行的解决办法,结合你的场景来选:

1. 调整删除顺序(最直接的临时解决办法)

你的Java代码里犯了一个顺序错误:现在是先删父表prodlist的记录,再删子表prodstock的关联数据,这刚好搞反了!正确的顺序应该是先删除子表中关联的记录,再删除父表的记录

修改后的代码应该是这样的:

private void loginBut46ActionPerformed(java.awt.event.ActionEvent evt) { 
    if (prodlist.getSelectedRowCount() == 0) { 
        JOptionPane.showMessageDialog(rootPane, "Select Raw to View!"); 
    } else { 
        int r = prodlist.getSelectedRow(); 
        String id = prodlist.getValueAt(r,0).toString(); 
        String item_code = prodlist.getValueAt(r,1).toString(); 
        try { 
            // 先删子表关联数据
            DB.DB.statement("delete from prodstock where item_code='"+item_code+"'"); 
            // 再删父表记录
            DB.DB.statement("delete from prodlist where id = '"+id+"' "); 
        } catch (Exception ex) { 
            Logger.getLogger(Stock.class.getName()).log(Level.SEVERE, null, ex); 
        } 
    } 
}

⚠️ 额外提醒:你现在用字符串拼接SQL的方式存在SQL注入风险,建议改成PreparedStatement来避免这个问题,比如:

try (Connection conn = DB.DB.getConnection()) {
    // 先删子表
    String deleteStockSql = "delete from prodstock where item_code = ?";
    PreparedStatement pstmt1 = conn.prepareStatement(deleteStockSql);
    pstmt1.setString(1, item_code);
    pstmt1.executeUpdate();
    
    // 再删父表
    String deleteListSql = "delete from prodlist where id = ?";
    PreparedStatement pstmt2 = conn.prepareStatement(deleteListSql);
    pstmt2.setString(1, id);
    pstmt2.executeUpdate();
} catch (Exception ex) {
    Logger.getLogger(Stock.class.getName()).log(Level.SEVERE, null, ex);
}

2. 修改外键的删除规则(一劳永逸的方案)

如果希望以后删除父表记录时,子表的关联数据能自动处理,可以修改外键的ON DELETE规则,常用的有两种:

  • ON DELETE CASCADE:删除父表记录时,自动删除子表中所有关联的记录
  • ON DELETE SET NULL:删除父表记录时,把子表中关联字段的值设为NULL(前提是prodstock.item_code字段允许为NULL)

你可以用SQL语句修改外键:

-- 先删除旧的外键约束
ALTER TABLE prodstock DROP FOREIGN KEY fk_prodstock_prodlist1;

-- 重新添加外键,设置ON DELETE CASCADE
ALTER TABLE prodstock 
ADD CONSTRAINT fk_prodstock_prodlist1 
FOREIGN KEY (item_code) REFERENCES prodlist(id) 
ON DELETE CASCADE 
ON UPDATE NO ACTION;

修改后,你只需要删除父表的记录,子表的关联数据会自动被删除,不用再手动写两次删除语句。

3. 临时禁用外键约束(不推荐,仅用于特殊场景)

如果你只是临时需要删除数据,不想改规则也不想按顺序删,可以临时禁用外键约束,但这会带来数据一致性风险,谨慎使用:

SET FOREIGN_KEY_CHECKS = 0;
-- 执行你的删除操作
DELETE FROM prodlist WHERE id = 'xxx';
DELETE FROM prodstock WHERE item_code = 'xxx';
-- 恢复外键约束
SET FOREIGN_KEY_CHECKS = 1;

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

火山引擎 最新活动