如何在循环引用数据库结构中保留数据完整性?

时间:2018-02-13 10:01:03

标签: database database-design reference database-relations

我已经研究了一些DataBase规范化和设计方法来正确构建数据,并且已经读到循环引用不是最佳的,因为它会危害数据的完整性。我有一个数据结构,我无法弄清楚如何消除循环引用或确保没有引入错误的引用。

数据库要求:

  1. 每种水果都需要特定于水果的属性
  2. 水果交付需要包含的水果类型
  3. 水果交付需要指定所有应用属性
  4. 水果交付不能引用不包含的水果类型属性
  5. 我想出的设计是:

    enter image description here 这样做的问题是,可以在交付包含FruitTypeID = 1的情况下输入可能的数据,但它链接到FruitTypeID = 2的属性。

    解决此问题的一种可能方法是创建一个触发器,强制执行属性只能链接到相同FruitType的交付。但我不喜欢它,因为它看起来很脆弱而且不太可靠。另一种方法是以某种方式消除这个数据的圆圈,但我无法找到一种方法,仍然符合要求。

    所以问题是我如何确保这些数据的数据完整性并且仍符合规范?

2 个答案:

答案 0 :(得分:2)

您没有循环引用。多对一关联指向一方的方向。你所拥有的是两条需要保持一致的关联路径。

您可以通过将函数依赖项AttributeID -> FruitTypeIDDeliveryID -> FruitTypeID非规范化为Attribute_Fruit,然后创建两个复合FK约束来实现:

CREATE TABLE Attribute (
    ID INT NOT NULL,
    FruitTypeID INT NOT NULL,
    Name VARCHAR(255) NOT NULL,
    PRIMARY KEY (ID),
    FOREIGN KEY (FruitTypeID) REFERENCES FruitType (ID),
    UNIQUE KEY (ID, FruitTypeID)
);

CREATE TABLE Delivery (
    ID INT NOT NULL,
    FruitTypeID INT NOT NULL,
    Amount INT NOT NULL,
    PRIMARY KEY (ID),
    FOREIGN KEY (FruitTypeID) REFERENCES FruitType (ID),
    UNIQUE KEY (ID, FruitTypeID)
);

我向AttributeDelivery添加了复合唯一键,以支持Attribute_Fruit表上的复合FK约束:

CREATE TABLE Attribute_Fruit (
    AttributeID INT NOT NULL,
    DeliveryID INT NOT NULL,
    FruitTypeID INT NOT NULL,
    PRIMARY KEY (AttributeID, DeliveryID),
    FOREIGN KEY (AttributeID, FruitTypeID) REFERENCES Attribute (ID, FruitTypeID),
    FOREIGN KEY (DeliveryID, FruitTypeID) REFERENCES Delivery (ID, FruitTypeID)
);

重叠的复合FK约束将强制实现您正在寻找的一致性。 FruitTypeID中的Attribute_Fruit在逻辑上是冗余的,但是对于完整性是必需的,并且由于FK约束,不存在更新异常的风险。

正如您所提到的,触发器是实现相同目标的另一种方式,并且正确实施,它们是可靠的而不是脆弱的。但是,我认为上述方法更简单。

答案 1 :(得分:1)

您需要做的是认识到“水果属性”不是交付的属性,而只是水果的属性。因此,您应该将交付模型与交付项目中的多对多关系进行建模,并且没有提及水果属性。

更好的是:拼出这些矩形应该意味着什么。也就是说,拼出这些表中的行事实表明现实世界中发生的事情。这样做,你会发现自己正在考虑问题。您将发现自己理解 所有中适用于您的业务案例的方面的问题。解决方案将自然而然地实现。而且很可能会涉及比你在这里更多的矩形。你目前还没有这样做。至少你还没有向我们提供任何细节。任何试图回应的人都会被迫进行猜测,这可能是无可救药的。就像我在第一段中所做的猜测一样(例如,我假设没有必要记录哪些“属性”已经在旧的交付中“交付”,这是在对某些属性应用之前完成的。一些水果)。