2010-06-28 128 views
0

下表定义:删除触发器替代“ON DELETE CASCADE”以避免“多个级联路径”?

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可能的,因为有多个级联路径。

我想我们在order列创建无ON DELETE CASCADE订单明细,让我们看看是否有可能实施参照完整性与含触发删除订单时:

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

触发器触发后Orders中删除,所以它是不可能的(DELETE语句与REFERENCE约束冲突)。

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

两个问题:

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

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

回答

1

我会避免这个问题,因为它可以从加入订单派生出来,因为不会将客户置于OrderDetails中。

即使使用外键,也不会阻止OrderDetails中的Customer与Orders中的Customer不同。

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

+0

我没有意识到“因为它”的差异 - 我立即失去了对触发器的胃口,设计。 – Gerard 2010-06-28 11:29:56

1

当然,它不正确,在OrderDetails中有CustomerId没有意义。这会给你一种传递依赖。
此外 - 根据您的实际模型 - 如果任何订单与其相关,则决不允许删除客户。你还是该计划是一个布尔值,或尤为明显日期字段一样DeadCustomer:/

对于结构:
客户:ID,姓名等
订单:的OrderId,订购日期,客户ID ...
订单明细: OrderId,ProductId,Quant,UnitPrice ...
产品:产品编号,说明,状态,单价...

+0

你的回答很有道理。但是我没有尝试删除一个客户,而是一个订单。 – Gerard 2010-06-28 11:23:40