Sha*_*ght 6 schema normalization database-design
假设您有一个装满小部件的仓库。仓库中的每个小部件都存储在仓库内的特定可识别位置。您可能有一个如下所示的架构:
小部件也可以(可选)位于仓库中的购物车上,这可能会导致这样的模式:
但是,出现了一个问题,因为购物车也只能位于仓库内的一个位置,这将先前的模式变成了这样:
但是,此模式是非规范化的,可能会导致异常,例如数据是:
widgetID storageLocationID 购物车ID ================================ 1 foo 2 巴
尽管两个小部件位于同一个购物车上,但数据库将它们显示在不同的位置,这是不可能的。
如果需要购物车,通过简单地从Widgets表中删除storageLocationID来解决这个标准化问题会相对简单。但是,由于不需要购物车,该解决方案将不起作用。
如何构造这些数据以消除异常情况?
您可以将手推车视为存储位置。
只需将属性添加到表中,以便可以将位置标识为“cart”或“shelf”类型,如下所示:
如果需要层次结构 - 例如,如果购物车可能存储在存储位置本身 - 您可以在存储位置表中定义层次结构。
这不是一个完美的解决方案 - 它可能难以执行限制,即推车必须存在于存储位置(如隔间或过道)。
然而,在大多数数据库引擎中,使用 CHECK 约束在这里强制执行一些业务逻辑是很简单的。
您可以通过更改FOREIGN KEY
约束(从Widgets
到Carts
)以包括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)