如何对多个表强制执行约束?

Mar*_*ger 5 erd constraint

我有以下五个表:

  • 产品
  • 特征
  • 供应商
  • 供应商_产品
  • PROVIDER_FEATURE

逻辑如下:

泛型PRODUCT可以有一个或多个FEATUREs。有不同的PROVIDERs 提供相同的产品,但具有不同的细节,同样的FEATUREs,也具有不同的细节。

问题是,使用这个 ERD,我可以创建一个PRODUCT带有FEATUREf1的p1和一个PRODUCT带有FEATUREf2的p2 。然后我创建PROVIDERpv1。现在我可以PROVIDER_PRODUCTPROVIDERpv1 和PRODUCTp1创建一个pvp1 。但是当我创建一个PROVIDER_FEATUREpvp1 时,我应该只被允许添加FEATUREf1,因为这是FEATURE通过PROVIDER_PRODUCT表链接到 p1 的那个。但是我也可以添加一个FEATUREf2。

如何创建一个约束防止进入用户PROVIDER_FEATURE即是其中一部分FEATURE即是其中一部分PRODUCT,但事实并非PRODUCTPROVIDER_PRODUCT是对PROVIDER_FEATURE?我需要在存储过程中解决这个问题,还是有更优雅的方法来强制执行?

+-------------------+       +--------------------+
|                   |       |                    |
| PRODUCT           +-----> | FEATURE            |
|                   |       |                    |
+---------+---------+       +----------+---------+
          |                            |          
          |                            |          
          v                            v          

+-------------------+       +--------------------+
|                   |       |                    |
| PROVIDER_PRODUCT  +-----> | PROVIDER_FEATURE   |
|                   |       |                    |
+-------------------+       +--------------------+

          ^                                       
          |                                       
          |                                       
+---------+---------+                             
|                   |                             
| PROVIDER          |                             
|                   |                             
+-------------------+                             
Run Code Online (Sandbox Code Playgroud)

Tod*_*ett 6

这可以通过使用重叠的级联键轻松完成。这是使用 Oracle Data Modeler 的示例(请注意,此工具中存在错误或配置问题,因为 Provider_Feature 表应将每一列显示为 PF,表示 PK 和 FK):

在此处输入图片说明

在此示例中,供应商产品的 PK 包括提供的产品编号,功能 PK 包括该产品支持的功能编号。Provider_Feature 中的产品编号是返回到 Provider 产品和功能的 FK。因此,FK 约束阻止为尚未实例化为产品功能可能性的产品功能组合插入提供者功能。

此解决方案假定功能由产品标识 - 即功能不能存在于产品的上下文之外。该假设可能是有效的,因为功能本身对产品的上下文没有意义。但是,如果您确实想要实例化可以包含在多个产品中的功能,那么您只需添加一个 Feature 表并使当前的 Feature 表成为 Product_Feature 表。

数据库设计者通常假设每个表都必须有自己的“标识符”。没有东西会离事实很远。请参阅Fabian Pascal关于此主题的优秀博客文章。向每个表添加代理键意味着您尝试强制执行的自然业务规则不能再通过 PK 和 FK 约束以声明方式强制执行,正如您发现的那样。如果由于某种原因您必须使用 SK,您唯一的选择是使用触发器在程序上强制执行约束。这个选项的问题要大得多。首先,您必须编写、调试、测试和维护触发器。数据库专业人员的应用数学这本书提供了极好的细节,说明使用程序逻辑以充分执行的方式表达约束有多困难。其次,触发器本身有时会成为性能抑制剂,因为它们是连续执行的。

我的建议是使用自然的声明式方法。