删除触发器作为“ON DELETE CASCADE”的替换以避免“多个级联路径”?

时间:2010-06-28 10:34:40

标签: sql-server triggers referential-integrity

下表定义:

   CREATE TABLE Customers( id INT NOT NULL PRIMARY KEY, name [varchar](50) )

    CREATE TABLE Orders ( id INT NOT NULL PRIMARY KEY, 
                          customer INT FOREIGN KEY 
                          REFERENCES Customers(id) ON DELETE CASCADE )

    CREATE TABLE OrderDetails ( id INT NOT NULL PRIMARY KEY, 
                                order INT FOREIGN KEY REFERENCES Orders(id) ON DELETE CASCADE, 
                                customer INT FOREIGN KEY REFERENCES Customers(id) ON DELETE CASCADE  )

在sql server中是不可能的,因为有多个级联路径。

我认为让我们在ON DELETE CASCADE列上创建没有order的OrderDetails,让我们看看在删除包含以下内容的触发器的订单时是否可以强制执行参照完整性:

DELETE FROM OrderDetails
    FROM Deleted d
    INNER JOIN OrderDetails od
    ON od.order = d.id

触发器在Orders中删除后触发,因此不可能(DELETE语句与REFERENCE约束冲突)。

我认为问题在于模型设计,从OrderDetails到Customers的引用是一个糟糕的设计。但是,否则可以为属于不同客户的订单创建OrderDetails。

两个问题:

  • 什么是最好的模型设计?
  • 是否可以使用触发器?

编辑:我从OrderDetails中删除了对客户的引用,这没有任何意义。 这解决了所有问题。

2 个答案:

答案 0 :(得分:1)

我会避免这个问题,因为它根本没有将Customer放在OrderDetails中,因为它可以通过加入Orders来实现。

因为它与外键一致,所以没有任何东西阻止OrderDetails中的Customer与Orders中的Customer不同。

另外你真的想要为此进行级联删除吗?据推测,该企业将需要一些历史订单记录。

答案 1 :(得分:1)

当然,这是不正确的,在OrderDetails中拥有CustomerId是没有意义的。这会给你一种传递依赖 此外 - 根据您的真实模型 - 如果任何订单与客户相关,则绝不允许删除客户。您应该规划一个布尔值,或者像DeadCustomer这样的Date字段:/

结构:
客户:身份证,姓名等 订单:OrderId,OrderDate,CustID ...
OrderDetails:OrderId,ProductId,Quant,UnitPrice ...
产品:ProductId,Description,Status,UnitPrice ......