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表。