2010-06-28 129 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