SQL Server表设计与表具有两个其他表的外键

时间:2014-08-26 19:51:02

标签: sql sql-server

我有四张桌子,
DiscountCode描述折扣。 捆绑产品基本上作为产品销售,因此它包含产品代码 作为产品销售的产品,因此它还包含产品代码 ProductDiscount代码用于描述Bundle / Product可以有多个与之关联的折扣代码的事实。

**Discount Code**
Id
Name
Code  ex. SUMMER10  ie 10% off summer products
...

**Bundles**
Id
Name
ProductCode  *Unique*  Ex..ABC123
...

**Products**
Id
Name
ProductCode  *Unique*  Ex.. XYZ1234
...

**ProductDiscountCode**
DiscountId
ProductCode   FK to both Products.ProductCode  AND Bundles.ProductCode

Records in ProductDiscountCode:
1   ABC123
1   XYZ1234
1   URS576  <-- prevent this if Prod or Bundle does NOT contain URS576

我的问题是关于Ternary表中的ProductCode。现在保持谨慎PELASE SQL不是我的强项!可以/应该将三元表中的ProductCode列外键键入两个单独的表,以尝试将其内容限制为Bundle表或Product表中包含的EITHER的产品代码,假设bundle和products中的productcode是唯一的两个表之间(由业务规则强制执行)。或者ProductDiscountCode表是否需要以下

**ProductDiscountCode**
DiscountId
ProductCode  FK to ProductCode in Product
BundleCode   FK to ProductCode in Bundle

3 个答案:

答案 0 :(得分:1)

好的,尝试约束同一个字段的两个不同的FK永远不是一个好主意,这是不正确设计的标志。

如果未使用产品表中的产品代码,为什么捆绑一个单独的表?为什么不在产品表中添加一列来确定订单项是捆绑产品还是单个产品,并在那里停止?

答案 1 :(得分:0)

如果您要使用外键,那么每个值必须作为另一个表上的键存在,因此如果列中包含产品密钥,则不能约束它们的产品密钥,反之亦然。

如果您需要确保参照完整性,那么您需要有两个Nullable列。

您可能还应该有一个Check Constraint来确保只有一个代码为空。

CREATE TABLE ProductDiscountCode
(
DiscountId int,
ProductCode  varchar(12) null,
BundleCode   varchar(12) null,

CONSTRAINT ProductDiscountCode_PK PRIMARY KEY(DiscountId),

CONSTRAINT FK_ProductDiscountCode_DiscountId FOREIGN KEY (DiscountId) REFERENCES DiscountCode (Id),
CONSTRAINT FK_ProductDiscountCode_BundleCode FOREIGN KEY (BundleCode) REFERENCES Bundle (ProductCode),
CONSTRAINT FK_ProductDiscountCode_ProductCode FOREIGN KEY (ProductCode) REFERENCES Product (ProductCode),

CONSTRAINT ProductCodeExists CHECK (
                                   (ProductCode IS NULL AND BundleCode IS NOT  NULL) 
                                   OR 
                                   (ProductCode IS NOT NULL AND BundleCode IS NULL)
                                   )
)

如果出于某种原因,您确实需要能够将产品代码显示为单个列,那么您可以按照以下方式执行操作

CREATE TABLE ProductDiscountCode
(
DiscountId int,
SingleProductCode  varchar(12) null,
BundleCode   varchar(12) null,
ProductCode as ISNULL (SingleProductCode  ,BundleCode  ) ,
CONSTRAINT ProductDiscountCode_PK PRIMARY KEY(DiscountId),
CONSTRAINT FK_ProductDiscountCode_DiscountId FOREIGN KEY (DiscountId) REFERENCES DiscountCode (Id),
CONSTRAINT FK_ProductDiscountCode_BundleCode FOREIGN KEY (BundleCode) REFERENCES Bundle (ProductCode),
CONSTRAINT FK_ProductDiscountCode_SingleProductCode FOREIGN KEY (SingleProductCode) REFERENCES Product (ProductCode),
CONSTRAINT SingleProductCodeExists CHECK ((SingleProductCode IS NULL AND BundleCode IS NOT  NULL) OR (SingleProductCode IS NOT NULL AND BundleCode IS NULL))
)

但你首先要问自己,首先是否真的需要使用外键限制。

产品代码有两列可以略微加快您的Select查询速度,但是必须决定将更新中的产品代码存储在哪一列,删除和插入将变得更加复杂。

答案 2 :(得分:0)

请先看一下主题:Multiple foreign key constraints on a single column in SQL Server 2008

ProductCode是Bundle中的FK,然后您需要另一个外键到ProductDiscountCode中的同一列。你是双引用相同的字段,这似乎不是很好的设计。您应该在插入时限制表中的值,约束不适用于所有类型的验证。