当可选字段导致非规范化时,如何规范化数据库?

Sha*_*ght 6 schema normalization database-design

假设您有一个装满小部件的仓库。仓库中的每个小部件都存储在仓库内的特定可识别位置。您可能有一个如下所示的架构:

原始布局

小部件也可以(可选)位于仓库中的购物车上,这可能会导致这样的模式:

添加到架构的购物车

但是,出现了一个问题,因为购物车也只能位于仓库内的一个位置,这将先前的模式变成了这样:

非规范化模式

但是,此模式是非规范化的,可能会导致异常,例如数据是:

widgetID storageLocationID 购物车ID
================================
1 foo
2 巴

尽管两个小部件位于同一个购物车上,但数据库将它们显示在不同的位置,这是不可能的。

如果需要购物车,通过简单地从Widgets表中删除storageLocationID来解决这个标准化问题会相对简单。但是,由于不需要购物车,该解决方案将不起作用。

如何构造这些数据以消除异常情况?

Nat*_*lly 7

您可以将手推车视为存储位置。

只需将属性添加到表中,以便可以将位置标识为“cart”或“shelf”类型,如下所示:

可能的标准化解决方案 1

如果需要层次结构 - 例如,如果购物车可能存储在存储位置本身 - 您可以在存储位置表中定义层次结构。

可能的标准化解决方案 2

这不是一个完美的解决方案 - 它可能难以执行限制,即推车必须存在于存储位置(如隔间或过道)。

然而,在大多数数据库引擎中,使用 CHECK 约束在这里强制执行一些业务逻辑是很简单的。


ype*_*eᵀᴹ 7

您可以通过更改FOREIGN KEY约束(从WidgetsCarts)以包括StorageLocationID

CREATE TABLE Widgets
  ( widgetID              NOT NULL
  , storageLocationID     NOT NULL
  , cartID                NULL
  , PRIMARY KEY (widgetID)
  , FOREIGN KEY (storageLocationID)
      REFERENCES StorageLocations (storageLocationID)
  , FOREIGN KEY (storageLocationID, cartID)
      REFERENCES Carts (storageLocationID, cartID)
  ) ;
Run Code Online (Sandbox Code Playgroud)

这通常需要对 的UNIQUE约束(或索引)Carts

CREATE TABLE Carts 
  ( cartID                NOT NULL
  , storageLocationID     NOT NULL
  , PRIMARY KEY (cartID)
  , FOREIGN KEY (storageLocationID)
      REFERENCES StorageLocations (storageLocationID)
  , UNIQUE (storageLocationID, cartID)
  ) ;
Run Code Online (Sandbox Code Playgroud)


小智 3

你可以尝试创建这样的东西(请原谅图像的粗糙):

与 storagelocations 和 carts 相关的位置表,其中 cartid 可为空