我想为以下场景设置表约束,我不确定如何操作,或者甚至可以在SQL Server 2005中使用。
我有三张桌子A,B,C。 C是B的子级.B将有一个可选的外键(可能为null)引用A.出于性能原因,我还希望表C对表A具有相同的外键引用。表C上的约束应该是C必须引用其父级(B),并且还具有与其父级相同的外键引用。
有人对如何做到这一点有任何想法吗?
答案 0 :(得分:5)
我认为没有必要明确强制执行从C到A的关系。只需按照从C到B到A的链。
答案 1 :(得分:2)
一般来说,我没有看到这样做的具体原因 - 但是,你确实问过。
要理解的是,关系模型不必遵循OO模型。
这是呈现Customer-Order-LineItem
的标准方式。没错。
如果我想查找属于客户的所有订单项,我必须通过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 ;
假设我稍微修改了一下键,比如:
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)。
答案 2 :(得分:1)
用于提高性能的非规范化非常常见,特别是如果您有证据显示其价值。我认为你有充分的理由这样做,所以我不会解决这个问题。
您是否想过在C上设置一个插入触发器,它根据表B中的查找设置引用表A的列?您可能还需要在C和B上更新触发器以确保它始终保持同步。这将确保表C中引用表A的列始终是正确的,即使它没有被实际约束“强制执行”。
答案 3 :(得分:0)
我有三张桌子A,B,C。 C是一个 B. B的孩子将有一个可选的 外键(可以为null)引用 答:出于性能原因,我也想要 表C具有相同的外键 参考表A.约束 在表C上应该是C必须的 引用其父母(B)也有 与A相同的外键引用 它的父母。
你可以让表B有一个双主键(A的键,然后说一个标识),然后用它来链接到C.这不允许你在B上有一个空的外键引用,但是外键不允许为null。
真的如果你已经设置了正确的索引等,就没有真正需要将A的键推到C.将它连接到表B以获得A的键不会有太大的性能损失(几乎没有)。
答案 4 :(得分:0)
看起来常见的情况是你有A的密钥而你需要C中所有匹配的行。在这种情况下,下面的查询应该很快:
select C.*
from B
join C on C.Bid = B.Bid
where C.Aid = <value>
使用适当的索引,这应该与在C上使用Aid一样快,因为它们都需要索引扫描,然后将结果连接到C表。