代码之家  ›  专栏  ›  技术社区  ›  drew

检查删除行是否安全

  •  5
  • drew  · 技术社区  · 15 年前

    我希望能够检查在SQL Server 2008中从表中删除行是否会由于外键冲突而失败,而不尝试删除它。

    基本上,我不想给用户显示一个delete按钮,如果他们不能删除它,因为键在其他地方使用。

    我在应用程序中的许多地方都需要这个,所以不想真的需要手动编写检查来查看删除行是否安全。有什么建议可以达到这个目的吗?

    我使用实体框架来访问数据。

    7 回复  |  直到 15 年前
        1
  •  2
  •   Donnie    15 年前

    没有快速简便的方法来检查这个。你可以用 information_schema ,但毫无疑问,这将是丑陋的,并不是很快。

    绝对的最佳选择是在每个位置验证所需的几行自定义代码。

    另一个选择是启动一个事务,尝试删除。如果失败了,你知道的。如果成功,回滚事务,您就知道删除是可能的。这仍然很难看,而且使用事务的方式有点混乱,但它会起作用的。不过,请确保该表没有启用级联删除。

        2
  •  2
  •   gbn    15 年前

    查询时,对子表执行左联接。使用candelite计算值来决定是否应该显示按钮。如果每个父行有多个子行,则此处的计数将删除重复项。

    SELECT
       Col1, Col2, Col3, ...,
       CASE C.Existence WHEN 0 THEN 1 ELSE 0 END AS CanDelete
    FROM
       ParentTable P
       LEFT JOIN
       (
       SELECT COUNT(*) AS Existence, FKColumn
       FROM Childtable GROUP BY FKColumn
       ) C ON P.FKColumn = C.FKColumn
    WHERE
       P.Col = ...
    

    另一种可能是

    SIGN(C.Existence) AS HasChildRows
    
        3
  •  1
  •   Randy Minder    15 年前

    我在以前的申请中做过这种事。我创建了一个名为TryDelete()的函数。在方法中,我试图删除所需的行。如果我得到一个FK异常,我会捕获它并返回false。无论是真是假,我都将删除封装在一个事务中,然后将其回滚。

        4
  •  1
  •   veljkoz Danko Valkov    15 年前

    您可以在实体的一个部分类中添加一个方法,该方法将检查引用对象是否存在。

    例如,假设Entity1的集合为Entity2。基本上,在每个实体部分类中,您将编写一个属性 IsReferenced 这将:

    • 如果Entity1在Entity2中有任何项,则For Entity1返回true
    • 对于Entity2,如果有对Entity1的引用,则返回true

    正如您所猜测的,您将需要确保在获取中始终包含引用的值,或者,如果您正在附加到上下文中工作,则可以使用 .Load() 在里面 参考 在检查之前获取实体。这是一笔开销,这取决于你是否愿意为它“买单”。

    然后,您可以在需要时根据该元素属性显示/隐藏“delete”按钮,从而避免每次都要重复检查。

        5
  •  0
  •   Heiko Hatzfeld    15 年前

    我认为你有两个可能的选择,因为你不能保证所有的关系都会被映射到你的OM中,你必须在数据库中检查它。

    您可以尝试在事务内部进行实际的挖掘,然后回滚,但如果您必须使用级联删除来限制配置,则这也可以工作。。。

    另一种方法是从sysobjects表中提取所有约束,并验证每个表没有记录。但这将需要一些动态SQL,这也会变得相当混乱。

        6
  •  0
  •   Kam    15 年前

    如果你在数据库级别,我会加入所有可能存在冲突的表格。

    任何返回的记录都不能被删除,这意味着剩余的集合可以被删除。

        7
  •  0
  •   Damien_The_Unbeliever    15 年前

    假设数据库被多个用户(绝大多数用户)使用,那么在“检查”删除是可能的和用户可能决定删除行之间会有一个机会窗口,在此期间,其他人可能会执行一些否定测试结果的活动。

    这意味着您可能会显示Delete按钮,但是当您尝试删除时,它已经不可能了。此外,您可能不会显示删除按钮,但当用户决定要删除行(但找不到按钮)时,应该允许他们删除。

    没有办法避免这种比赛。如果人们愿意的话,我会让他们尝试删除,但是要准备好处理外键导致的失败。