Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 多列外键约束_Sql_Sql Server 2005_Database Design_Constraints_Foreign Key Relationship - Fatal编程技术网

Sql 多列外键约束

Sql 多列外键约束,sql,sql-server-2005,database-design,constraints,foreign-key-relationship,Sql,Sql Server 2005,Database Design,Constraints,Foreign Key Relationship,我想为以下场景设置表约束,但我不确定如何设置,或者在SQLServer2005中是否可以设置 我有三个表A、B、C。C是B的子表。B将有一个可选外键(可能为空)引用A。出于性能原因,我还希望表C对表A具有相同的外键引用。表C上的约束应为C必须引用其父表(B),并且对A具有与其父表相同的外键引用 有人想过怎么做吗 我有三张桌子A,B,C。C是A B.B.的孩子将有一个可选的 外键(可能为空)引用 出于性能原因,我也希望 表C具有相同的外键 参考表A。约束条件 在表C中,C必须 引用其父项(B),并

我想为以下场景设置表约束,但我不确定如何设置,或者在SQLServer2005中是否可以设置

我有三个表A、B、C。C是B的子表。B将有一个可选外键(可能为空)引用A。出于性能原因,我还希望表C对表A具有相同的外键引用。表C上的约束应为C必须引用其父表(B),并且对A具有与其父表相同的外键引用

有人想过怎么做吗

我有三张桌子A,B,C。C是A B.B.的孩子将有一个可选的 外键(可能为空)引用 出于性能原因,我也希望 表C具有相同的外键 参考表A。约束条件 在表C中,C必须 引用其父项(B),并具有 对A的外键引用与 它的父母

您可以让表B有一个双主键(a的键,然后说一个标识),然后使用它链接到C。虽然这不允许您在B上有一个空外键引用,但无论如何外键都不允许为空


实际上,如果您正确地设置了索引等,就不需要将a的键推送到C。将a的键连接到表B以获得a的键不会对性能造成太大影响(几乎没有)

我认为没有必要明确地强制执行从C到a的关系。只需遵循从C到B到a的链。

为了提高性能而进行的非规范化非常常见,特别是如果有证据表明其价值的话。我想你这样做是有充分的理由的,所以我就不说了


您是否想过在C上使用一个insert触发器,它根据表B中的查找设置引用表A的列?您可能还需要C和B上的更新触发器来确保它始终同步。这将确保表C中引用表A的列始终正确,即使它不是由实际约束“强制”的。

一般来说,我看不出这样做的具体原因——但是,您确实问过

需要理解的是,关系模型不必遵循OO模型。 这是显示客户订单行项目的标准方式。这没问题

如果我想找到属于某个客户的所有行项目,我必须通过
Order
表加入,类似于OO点符号(
customer.Order.LineItem

假设我稍微修改了一些关键点,如:

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)很难。

对于您来说,常见的情况是您拥有A的密钥,并且需要C中的所有匹配行。在这种情况下,以下查询应该很快:

select C.* 
from B
join C on C.Bid = B.Bid
where C.Aid = <value>
选择C.*
从B
按C.投标加入C.投标=B.投标
其中C.援助=

有了适当的索引,这应该和在C上有Aid一样快,因为它们都需要索引扫描,然后将结果加入C表。

我的反应是-删除C到A的额外链接-你证明了存在性能问题吗?或者这只是为了简化某些查询?主要是为了方便/快速检索。C是B的一个细节记录。在大多数情况下,我只希望C中的所有细节都由a的键引用。一个真实的例子怎么样?性能问题可能根本不存在,通过使用自然键,您可以直接加入。好主意!这是我发现我们不可能总是知道A的钥匙之前的第一个想法。嗯……也许我会试试加入。B通常不会被大量使用,这就是为什么我在表C中有a的键。90%的时间我只需要使用a的键从C中获取详细信息。我在事务量非常大的数据库中工作,因此性能至关重要。我可以测试一下你的想法,看看触发器会对性能产生什么影响,谢谢!
select C.* 
from B
join C on C.Bid = B.Bid
where C.Aid = <value>