6

我要爲以下情形設置表的約束,我不知道如何做到這一點,或者如果它在SQL Server 2005多列外鍵約束上

甚至有可能我有三個表A,B, C。 C是B的一個子元素。B將有一個可選的外鍵(可以爲null)引用A.出於性能原因,我也希望表C具有與表A相同的外鍵引用。表C上的約束應該是C必須引用其父代(B),並且也具有與A相同的外鍵引用作爲其父代。

任何人有任何想法如何做到這一點?

+4

我的反應是 - 刪除從C到A的額外鏈接 - 是否證明存在性能問題?或者這只是爲了簡化一些查詢的地方? – Randy 2010-12-23 15:55:52

+0

主要用於簡單/快速檢索。 C是B的一個詳細記錄。在大多數情況下,我只想在C中引用A的所有細節。 – eugene4968 2010-12-23 16:22:54

+0

真實例子怎麼樣?性能問題可能根本就不存在,並且使用自然鍵您可以直接加入。 – 2010-12-23 19:17:42

回答

2

一般來說,我沒有看到具體的原因做到這一點 - 但是,你確實問過。

要理解的是關係模型不必遵循OO模型。 這是呈現Customer-Order-LineItem的標準方式。這沒什麼錯。

alt text

如果我想找到屬於客戶的所有行項目,我必須通過Order表,類似於OO點 - 點符號(Customer.Order.LineItem)加入。

select * 
from Customer as c 
join Order as o on o.CustomerId = c.CustomerId 
join LineItem as i on i.OrderId = o.OrderId 
where CustomerID = 7 ; 

假設我修改密鑰的位,如:

alt text

CustomerOrderId是爲每一個客戶(1,2,3 ...)的順序的序列號和CustomerOrderItemId是每個客戶訂單的行項目序號(1,2,3 ...)。每個人很容易產生,如

-- next CustomerOrderId 
select coalesce(max(CustomerOrderId), 0) + 1 
from Order 
where CustomerId = specific_customer_id; 

-- next CustomerOrderItemId 
select coalesce(max(CustomerOrderItemId), 0) + 1 
from LineItem 
where CustomerId  = specific_customer_id 
    and CustomerOrderId = specific_customer_order_id; 

現在,如果我想找到屬於客戶(和一些客戶的數據)線項目,我可以跳過Order表。

select * 
from Customer as c 
join LineItem as i on i.CustomerId = c.CustomerId 
where CustomerID = 7 ; 

,如果我不從Customer表需要任何特定的數據,沒有必要加入的。將此與第一個示例進行比較 - 請記住,獲取訂單項是目標。

select * 
from LineItem 
where CustomerID = 7 ; 

因此,關係模型,通過傳播(自然)鍵,你不必總是連接「沿着關係路徑在每個站停」。

哪個更好?取決於你問的問題。

希望你能夠將基本原理轉化爲你的例子 - 我發現很難使用通用的(A,B,C)。

0

我有三個表A,B,C。 C是 孩子B. B的將有一個可選的 外鍵(可以爲null)引用 A.由於性能原因我也想 表C到具有相同的外鍵 參考表A上的約束 表C應該是C必須 參考其父母(B)並且還有 與A相同的外鍵參考 其父母。

你可以讓表B有一個雙主鍵(A的鍵,然後說一個標識),然後用它來鏈接到C.這將不允許你有一個空的外鍵引用但是,不管怎樣,外鍵不允許爲空。

真的,如果你有索引等設置正確,沒有一個真正的需要推動A的關鍵C.加入到表B獲得A的關鍵不會那麼多的表現擊中(像幾乎沒有)。

5

我不認爲有必要明確地執行從C到A的關係,只需按照從C鏈B到A

1

非規範化提高性能的目的,是很常見的,特別是如果你有證據顯示其價值。我假設你有充分的理由這樣做,所以我不會解決這個問題。

你有沒有想過只需在C上有一個插入觸發器,它根據表B中的查找來設置列引用表A?您可能還需要C和B上的更新觸發器,以確保它始終保持同步。這將確保引用表A的表C中的列始終是正確的,即使它沒有被實際約束「強制執行」。

0

看起來像普通UE的情況下,你是你有一個重點,你需要在C中的所有匹配的行。在這種情況下,下面的查詢要快:

select C.* 
from B 
join C on C.Bid = B.Bid 
where C.Aid = <value> 

適當的索引,這應該是與C上的Aid一樣快,因爲它們都需要索引掃描,然後將該結果連接到C表。