【问题标题】:Many-to-Many but sourced from multiple tables多对多但来自多个表
【发布时间】:2012-04-05 12:31:02
【问题描述】:

我应该运送一个包含可变内容的盒子并在数据库中跟踪它。我所有的项目(一个盒子的内容)都是不同的类型,需要不同的表来跟踪它们各自的信息,尽管每个项目类型都有相同的长度序列号(即 PK 是相同的数据类型)。我有一个 Boxes 表。

所以每个项目都有一个表(~7 个表)加上盒子表。我想创建一个BoxContents 表。我尝试创建一个包含两列的多对多关系中间表:一列用于BoxID,另一列用于ItemBarcode,其中BoxIDBoxes 表和ItemBarcode 上PK 的FK是 Items 表上每个 PK 的 FK(即我试图将多个表链接到同一列)。不出所料,这没有奏效。我试图插入一个项目,但除了一个 ItemBarcode 关系之外,其他所有关系都违反了 FK 约束。

如何构建我的关系以将几种类型的项目链接到一张表中的一个框?这是一种合乎逻辑的方法吗?您需要更多信息吗?

【问题讨论】:

    标签: sql sql-server-2008 database-design


    【解决方案1】:

    您需要一个类别层次结构(又名。类层次结构、子类型层次结构、继承层次结构......):

    3 main strategies 用于实现类别层次结构。如果你选择“all classes in one table”或“class per table”,那么无论你有多少kinds项,你只需要一个“链接”表来实现多对-很多关系。

    【讨论】:

      【解决方案2】:

      如果ItemBarcode 的值真正独一无二,我的第一选择是:

      编辑:添加了所需触发器的描述。

      • 添加触发器以强制条形码唯一性。 (每个项目表上的插入/更新触发器需要验证所有(新)分配的条形码都没有出现在其他项目表中。)
      • 使用单个 BoxId/ItemBarcode 表,在条形码端没有 FK 关系,但使用触发器确保它保持有效。 (关联表上的插入/更新触发器需要验证项目表中是否存在条形码。每个项目表上的删除触发器需要防止或级联删除关联表中的项目。更新触发器项目表需要更新和更改关联表中的条形码。这最后可以集成到前面项目符号中的插入/更新触发器中。)
      • 考虑使用所有项目的视图来访问ItemBarcode 的公共数据。

      我的第二个选择是 n BoxId/ItemBarcode 表用于 n 项类型。直截了当,但有点忙。这使得添加新的项目类型比需要的更加混乱。

      我不会使用BoxId/ItemTypeId/ItemBarcode 表。它通过再次关联ItemTypeIdItemBarcode 来反规范化数据,它不允许在条形码端使用 FK,它仍然需要触发器来确保完整性。

      不要害怕触发器。他们可以非常有效地解决一些问题。

      【讨论】:

      • 由于我以前没有使用过触发器,我怎么知道要检查哪个表来验证插入的条形码是否存在于正确的表中?每个项目的条形码都有自己的前缀我想我有一些 switch 语句可以解析条形码的一部分然后重定向到另一个存储过程?
      • 哦!我想我明白了!当我想在框和项目之间建立链接(即填充 boxcontents 表)时,我不添加到“摘要项目”中 我插入摘要表的同时插入单个项目表!那么条目总是正确的。
      • @Brad - 当您将商品添加到盒子时,您只关心商品的条形码是否在所有商品条形码的union 中。制作提供unionview 可以简化事情。触发器用于强制执行 deferential 完整性,即您自己的奇数版本的引用完整性,因此数据不会*被破坏。 (* - 挑战留给感兴趣的读者。)
      • 我最终使用了视图方法(不同表中所有相关 PK 的联合)非常感谢您的帮助。回复较晚,抱歉。我经历了很多考验!
      【解决方案3】:

      关系数据库不擅长处理这类问题。您的基本设计是正确的 - 表之间的 FK 的 关联 表。

      您的选择是:

      1. 在您的关联表中有多个列 - 每个项目表一个列
      2. 将商品数据合并到一个商品表中

      我会选择选项 2。

      【讨论】:

      • 我觉得无论哪种方式我都会得到带有空白字段的行。如果我选择选项 1。那么并非每个盒子都有所有类型的物品。如果我选择选项 2。并非每个项目都需要相同的信息列。空白字段似乎不是一个好主意。尤其是很多都是设计出来的,对吧?
      • 您可能最好将稀疏数据放在项目表中 - 它更易于管理,并且行大小有限且较小
      • 是的,很不幸,但我可以管理将所有这些表合并为一张。我想我需要在应用程序级别强制执行必填/N/A 字段。
      • 您始终可以在列上使用check 约束来强制每个项目类型都存在您需要的列,例如col1 int check ( item_type_id != 1 or (item_type_id = 1 and col1 is not null))
      猜你喜欢
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多