gpt4 book ai didi

sql - 如何创建多个一对一

转载 作者:太空狗 更新时间:2023-10-30 01:46:24 27 4
gpt4 key购买 nike

我有一个包含许多表的数据库,除了一点点之外一切看起来都不错......

Inventory Table <*-----1> Storage Table <1-----1> Van Table
^
1
|-------1> Warehouse Table

使用 Storage 表是因为 Van 和 Warehouse 表很相似,但是如何在 Storage 和 Warehouse/Van 表之间创建关系?它们必须是 1 到 1 是有道理的,因为存储对象只能是 1 个存储位置和类型。我确实将 Van/Warehouse 表链接到 StorageId 主键,然后添加约束以确保 Van 和 Warehouse 表不具有相同的 StorageId,但这似乎可以通过更好的方式完成。

我可以看到几种方法,但它们似乎都是错误的,所以任何帮助都会很好!

最佳答案

您正在使用继承(在实体关系建模中也称为“子类”或“类别”)。一般来说,在数据库中有3种表示方式:

  1. “一个表中的所有类”:只有一个表“覆盖”父类和所有子类(即具有所有父列和子列),并带有 CHECK 约束以确保正确的子集的字段是非 NULL(即两个不同的 child 不“混合”)。
  2. “每个表的具体类”:每个 child 都有一个不同的表,但没有父表。这需要在所有 child 中重复 parent 的关系(在您的情况下为库存 <- 存储)。
  3. “每张 table 上课”:为每个 child 准备一个父表和一个单独的表,这就是您想要做的。这是最干净的,但可能会降低一些性能(主要是在修改数据时,查询时不是那么多,因为您可以直接从子节点加入并跳过父节点)。

我通常更喜欢第 3 种方法,但在应用程序级别强制 child 的存在排他性。在数据库级别强制执行这两者有点麻烦,但如果 DBMS 支持延迟约束,则可以完成。例如:

enter image description here

CHECK (
(
(VAN_ID IS NOT NULL AND VAN_ID = STORAGE_ID)
AND WAREHOUSE_ID IS NULL
)
OR (
VAN_ID IS NULL
AND (WAREHOUSE_ID IS NOT NULL AND WAREHOUSE_ID = STORAGE_ID)
)
)

这将强制排他性(由于 CHECK)和存在(由于 CHECKFK1 的组合)/FK2) 的 child 。

不幸的是,MS SQL Server does not support deferred constraints ,但您可以将整个操作“隐藏”在存储过程后面,并禁止客户端直接修改表。


可以在没有延迟约束的情况下强制执行排他性:

enter image description here

STORAGE_TYPE 是一个类型鉴别符,通常是一个整数以节省空间(在上面的示例中,0 和 1 对您的应用程序是“已知的”并相应地进行解释)。

VAN.STORAGE_TYPEWAREHOUSE.STORAGE_TYPE 可以计算(也称为“计算”)列以节省存储空间并避免需要 CHECKs.

--- 编辑 ---

计算列将在 SQL Server 下像这样工作:

CREATE TABLE STORAGE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE tinyint NOT NULL,
UNIQUE (STORAGE_ID, STORAGE_TYPE)
);

CREATE TABLE VAN (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(0 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);

CREATE TABLE WAREHOUSE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(1 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);

-- We can make a new van.
INSERT INTO STORAGE VALUES (100, 0);
INSERT INTO VAN VALUES (100);

-- But we cannot make it a warehouse too.
INSERT INTO WAREHOUSE VALUES (100);
-- Msg 547, Level 16, State 0, Line 24
-- The INSERT statement conflicted with the FOREIGN KEY constraint "FK__WAREHOUSE__695C9DA1". The conflict occurred in database "master", table "dbo.STORAGE".

不幸的是,SQL Server 要求在外键中使用的计算列 是 PERSISTED。其他数据库可能没有这个限制(例如Oracle的虚拟列),可以节省一些存储空间。

关于sql - 如何创建多个一对一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9174200/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com