【问题标题】:Indicating primary/default record in database指示数据库中的主要/默认记录
【发布时间】:2012-01-25 05:01:28
【问题描述】:

我一直在纠结如何指出数据库中的某条记录是“后备”或默认条目。我也一直在努力解决如何将我的问题简化为一个简单的问题陈述。我将不得不提供一个例子。

假设您正在构建一个非常简单的运输应用程序。您将接受订单并需要决定从哪个仓库发货。

假设您有几个城市拥有自己的专用仓库*;如果订单来自其中一个城市,您将从该城市的仓库发货。如果订单来自任何其他城市,您想从某个其他仓库发货。我们将某个其他仓库称为后备仓库。

您可能会决定这样的架构:

Warehouses
    WarehouseId
    Name

WarehouseCities
    WarehouseId
    CityName

解决方案必须强制执行零个或一个后备仓库。

如果没有为相关城市指定任何仓库,您需要一种方法来指明应该使用哪个仓库。如果它真的很重要,您可以在 SQL Server 2008 上执行此操作。

编辑:明确地说,所有有效城市都不存在于 WarehouseCities 表中。可能会收到未在 WarehouseCities 中列出的城市的订单。在这种情况下,我们需要能够选择回退仓库。

如果允许任意数量的默认仓库,或者如果我将默认仓库分配给例如州,我将使用 DefaultWarehouse 表。我可以在这里使用这样的表格,但我需要将其限制为恰好一行,这感觉不对。

您将如何指示后备仓库?


*当然,在这个例子中,我们排除了可能存在多个同名城市的可能性。您正在为其构建此应用程序的国家/地区对所有城市名称严格执行唯一性约束。

【问题讨论】:

  • 什么版本的 SQL Server? 2008 年?
  • 我很惊讶这很重要。我希望避免需要特定版本的 SQL Server 的深奥解决方案;感觉不像是需要独占功能的问题。也就是说,现在是 2008 年。我会更新标签和问题。
  • fyi ...我认为这是 SQL 中常见设计问题的有效问题 - +1。此外,它并不深奥,但我立即想到了在 sql 2008 中添加的过滤索引。
  • @davidmontoyago - 过滤索引可能是过去需要触发器的强制 DRI/唯一性的一种非常相关的方式。我们只在 sql 2008 中得到过滤索引。
  • @davidmontoyago - 平台可能与问题无关,但与解决方案高度相关。

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


【解决方案1】:

我了解您的问题,但对部分问题有疑问,所以我会更笼统一些。

  • 如果可能的话,我会将仓库/备份仓库数据与您的库存数据一起存储(直接悬挂仓库,或者如果它是库存表中的特定产品)。
  • 如果必须通过您的业务逻辑计算设置,那么记录应该挂在 order/order_item 表中

就如何在 SQL 中实现结构而言,我将假设所有订单都从一个仓库发货,并且必须将发货挂在订单表之外(但这些想法应该适用于其他地方):

  • 实施零/一备份仓库的旧方法是挂起 Orders 表的 Warehouse_Source 记录并包含“IsPrimary”字段或“ShippingPriority”,然后包含包含 OrderID 和 IsPrimary/ 的复合唯一索引运输优先。

  • 如果您只有一个备份仓库,您可以在订单中添加 ShippingSource_WareHouseID 和 ShippingSource_Backup_WareHouseID 字段。不过,这不是我要走的路。

在 SQL 2008 及更高版本中,我们新增了 Filtered Indexes。这些允许您将 WHERE 子句添加到索引中 - 从而产生更紧凑的索引。它还有一个额外的好处,就是允许您完成一些过去只能通过触发器才能完成的事情。

  • 您可以在 OrderID & IsPrimary/ShippingPriority (WHERE IsPrimary = 0) 上放置一个唯一过滤索引。

如果您希望我进一步解释,请添加评论或类似内容。

【讨论】:

  • 我喜欢过滤索引的想法。直觉上,只有一个 Primary 仓库可能已经很有意义了。过滤索引似乎不太容易被发现,但我可以使用它来帮助执行一些应该是直观的东西。谢谢!
  • 过滤索引与更传统的唯一索引 (sp_helpindex MyTable) 一样容易被发现,并开辟了一些思考 D.R.I. 的新方法
【解决方案2】:

re: 我应该如何指出数据库中的某条记录是“后备”或默认条目

使用另一列 isFallback,保存一个二进制值。我假设您的后备仓库不会有任何与之关联的城市。

【讨论】:

  • 备用仓库可能有与之关联的城市,但这不会影响 isFallback 列的使用。但是,拥有 isFallback 列并不能强制要求,最多可以将一个仓库标记为后备仓库。
  • 然后,就像您说的,您可以使用您的备用仓库 ID 创建另一个表并强制执行 RI。这似乎有点矫枉过正,它可能是,但它满足您的要求。我认为您在这里没有遗漏任何东西。
【解决方案3】:

在我看来,后备仓库毕竟只是另一个仓库,如果我理解的话,WarehouseCities 中的每条记录都引用了 Warehouses 中的一条记录:

WarehouseCities(*)...(1)Warehouses 

这意味着如果有一百个城市没有专用仓库,它们都将引用特定备用仓库的 id。所以我没有看到任何问题(这让我觉得我不明白这个问题),即使模型看起来定义得很好。

现在您可以通过 Warehouses 上的 type_warehouse 等属性来识别仓库是否为后备仓库。

评论后编辑

假设 WarehouseCities 中不存在的城市只有一个备用仓库,我建议将备用仓库保留为另一个仓库,并将其 Id (WarehouseId) 作为应用程序参数(可能是参数表?),当然,此解决方案是以编程方式进行的,并不附加到您的数据库平台。

【讨论】:

  • 我解释得不好的问题是,给定的城市可能不在 WarehouseCities 表中。我想要一个解决方案,如果 WarehouseCities 中不存在城市,我可以选择备用仓库。我会更新我的问题以明确这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 2018-03-26
  • 2022-01-04
相关资源
最近更新 更多