删除父子记录而不使用删除级联

Posted

技术标签:

【中文标题】删除父子记录而不使用删除级联【英文标题】:Delete parent and child records without using on delete cascade 【发布时间】:2018-09-17 14:21:27 【问题描述】:

那么,让我们进入正题。我有一个项目,用户可以从数据库中删除记录,但当然如果我删除父记录,我会收到错误,因为它在另一个表中有子记录。所以,我想做的是我想删除父记录,当我删除它时,子记录中包含父键或主键的所有行也将被删除,而不使用级联。

下面是代码示例:

if (row != -1)
        
            tbl_employee.Rows.RemoveAt(row);

            int id = Convert.ToInt32(txt_employeeid.Text.ToString());
            employee emp = db.employees.Single(x => x.employeeid == id);
            db.employees.DeleteOnSubmit(emp);
db.SubmitChanges();
        
        else
        
            MessageBox.Show("Click the row first!");

        

但是,我有一个错误The DELETE statement conflicted with the REFERENCE constraint。我知道我可以使用on delete cascade,但是有没有其他的东西可以在不使用的情况下删除子记录?

【问题讨论】:

是不先删除子项就不能删除父项的问题吗?只需删除孩子,然后删除父母。不知道可能涉及到哪些引用表? 是的!但是我当然不能先删除孩子,如果用户想在不知道孩子的情况下删除父母怎么办?所以,我想做的是当用户删除父记录时,子记录也将被删除。对于引用,假设员工 id,将被删除的是员工表和生产表。 如果您不想在客户端执行此操作,可以使用触发器而不是触发器来执行此操作 您是否考虑过硬删除所有数据会造成什么损失?软删除会是一个更好的选择吗,即有一个类似于IsDeleted 的列,当它们删除时您设置为true。您需要添加逻辑来过滤掉已删除的记录,但会保持参照完整性。否则,为什么不能先删除子记录,因为您有父 id 来删除子行? 【参考方案1】:

使用Cascade Delete 是最简单的,但我同意这不是一个好的解决方案,因为您无法控制哪些子表可以被删除,哪些不能。

所以你还有两个选择:

    在删除主表之前删除客户端子表中的行(当然在同一个事务中) 删除instead of trigger 中子表(和主表行)中的行

后者的优点是它再次在数据库端完成,并且与其他解决方案一样,您还可以控制哪些表可以被删除,哪些不能。 如果你愿意,你甚至可以在里面放一些额外的支票。

【讨论】:

The latter has the advantage that it is done on the database side again, and give you control which tables may be deleted and which do not CASCADEs 还以 FOREIGN KEY 定义的形式精确控制在每个操作上删除哪些表。如果本机数据库功能可以完成这项工作,通常触发器是次要的选择。如果无法使用数据库,客户端是一个选项,但我个人只会留在级联。 @Alejandro 从 OP 的问题来看,我认为他不想使用 cascade delete 所以我只是总结了他的选择,在这种情况下,instead of trigger似乎是唯一剩下的选择来保留它在数据库方面。我在某些情况下自己使用它们,除非您一次删除几条 100 条记录,否则此处不会注意到性能问题 @Alejandro 我将问题中的文字更改为and like the other solutions also gives you control... 这样是否更清楚?

以上是关于删除父子记录而不使用删除级联的主要内容,如果未能解决你的问题,请参考以下文章

使用实体框架中的可选记录级联删除

Spring data JPA:如何启用级联删除而不引用父级中的子级?

oracle关于删除级联条件

ACCESS级联删除一对多关系的记录

Hibernate实体级联删除父或子

Fluent NHibernate 仅级联删除关联记录