【问题标题】:Enforce ONE to MANY relationship in SQL Server在 SQL Server 中强制执行 ONE to MANY 关系
【发布时间】:2011-02-08 01:11:32
【问题描述】:

我的数据库中有 2 个表。 表 1 'OrderItems' 和表 2 'Orders'。 每个“Order”可以有零个或多个“OrderItems”。 我定义了一个连接主键的 FK 约束:OrderId 和 OrderItemId,DeleteRule 设置为“Cascade”。 这样可以确保在我删除订单时删除所有 OrderItems。

我需要避免的是空订单。我需要确保一个订单至少有一个 OrderItem,否则一旦最后一个链接的 OrderItem 被删除,它就会被自动删除。我当然可以在我的应用程序中检查这个,但理想情况下数据库可以处理这个。

我使用 MS SQL Server 2008 和实体框架作为我的 ORM。

谢谢!

【问题讨论】:

    标签: sql-server entity-framework


    【解决方案1】:

    这种关系不能使用普通的关系规则强制执行;毕竟,您将如何添加订单?如果您无法在没有订单的情况下添加订单商品,但您不能在没有订单商品的情况下获得任何订单,那么您就会遇到先有鸡还是先有蛋的场景。

    您唯一真正的解决方案是在OrderItem 表上创建一个删除触发器,如果​​它是最后一项,则删除相应的订单。

    【讨论】:

    • 删除触发器是仅在 Delete 上触发还是会在每次更改时触发,正如@Dave Anderson 在下面建议的那样?
    • @santiagoIT:您可以定义将触发插入、更新和删除的触发器。
    • 如何轻松地让删除触发器了解已删除记录中的数据?例如,如果我删除所有超过两年的OrderItems,触发器是否能够识别相应的 OrderID,还是需要检查所有 0 个子订单的订单?
    • @djacobson:您可能想对触发器进行一些阅读,但简短的回答是触发器提供了两个“伪表”(我不确定实际术语,如果有的话) 称为INSERTEDDELETED。这些包含(分别)插入或删除的行。插入触发器只有INSERTED 中的值,删除触发器只有DELETED 中的值,更新触发器两者都有值(DELETED 中的旧行和INSERTED 中的新行)
    【解决方案2】:

    这种双向关系可能无法在 db 模式中强制执行。您可能需要在业务逻辑中强制执行此操作。

    【讨论】:

      【解决方案3】:

      我不知道执行此操作的基于约束的方法。您可能会成功地从OrderItem 表中删除触发器,检查“无子”Order 记录并删除这些记录...不过,这可能是一种重量级的“沸腾海洋”方法,您可能会正如@rcravens 建议的那样,最好在业务逻辑中捕捉这种场景。

      【讨论】:

      • 为什么在我的业务逻辑中这样做会更好?每次删除 OrderItem 时,我还必须检查 Order 是否还有其他 OrderItem。我假设删除触发器仅在删除时触发。
      • @santiagoIT True,但删除触发器可能无法识别已删除的 OrderItem 记录的 OrderID,因此必须扫描每个 Order 记录以查看它是否还有剩余的子记录(我可能是错的,但我不知道触发器无法从触发查询中获取此类信息)。如果您在业务逻辑中执行此检查,则可以保留受影响的 OrderID 并仅评估那些 Orders 以进行删除。
      • @santiagoIT 请随意忽略我之前的评论 - @Adam Robinson 已经解释了触发器在这方面的工作原理。
      【解决方案4】:

      考虑使用UPDATE TRIGGER 检查您是否还有剩余的订单商品,然后将订单存档。

      这将在对表中的行进行每次更改时触发,因此您应该仔细考虑逻辑和相关的性能影响。

      【讨论】:

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