库存数据库设计

这实际上不是一个关于“编程”(不是特定于任何语言或数据库)的问题,而是更多关于设计和体系结构的问题。这也是一个类型为“什么是做 X 的最好方式”的问题。我希望不会引起太多的“宗教”争议。

In the past I have developed systems that in one way or another, keep some form of inventory of items (not relevant what items). Some using languages/DB's that do not support transactions. In those cases I opted not to save item 手头数量 in a field in the item record. Instead the 手头数量 is calculated totaling inventory received - total of inventory sold. This has resulted in almost no discrepancies in inventory because of software. The tables are properly indexed and the performance is good. There is a archiving process in case the amount of record start to affect performance.

几年前,我开始在这家公司工作,我继承了一套跟踪库存的系统。但是这个数量在田地里被保存了下来。注册条目时,接收到的数量将添加到该项的数量字段中。当一个商品被出售时,数量被减去。这导致了差异。在我看来,这不是正确的方法,但这里以前的程序员对此深信不疑。

我想知道是否有一个共识,什么是正确的方式是设计这样的制度。还有什么资源可用,印刷或在线,以寻求这方面的指导。

谢谢

50463 次浏览

我会选择第一种方式

计算手头的数量 已收存货总额 库存出售

正确的方式,我的天。

编辑: 我也想把任何股票损失/损害纳入系统,但我相信你已经考虑到了这一点。

我在现在的公司见过这两种方法,肯定会倾向于第一种(根据股票交易计算总额)。

如果您只是在某个字段中存储总量,那么您不知道是如何得到这个数字的。没有事务历史记录,您最终可能会遇到问题。

我编写的上一个系统通过将每笔交易存储为正负数量的记录来跟踪股票。我发现它非常有效。

视情况而定,库存系统不仅仅是计算物品的数量。例如,出于会计目的,您可能需要了解基于 FIFO (先入先出)模型的库存的会计价值。这不能用简单的“已收存货总额-已出售存货总额”公式来计算。但他们的模型可能很容易计算,因为他们修改会计价值,因为他们去。我不想深入细节,因为这不是编程问题,但如果他们坚信这一点,也许你没有完全理解他们必须适应的所有需求。

重要的是要考虑现有的系统和改变它的成本和风险。我使用的数据库存储库存类似你的,但它包括审计周期和存储调整,就像收据。它看起来工作得很好,但是每个参与者都受过良好的训练,仓库工作人员并不能很快学会新的程序。

在您的例子中,如果您希望在不改变整个数据库结构的情况下进行更多的跟踪,那么我建议添加一个跟踪表(类似于您的“事务”解决方案) ,然后将更改记录到库存级别。将大多数更改更新到库存级别,以便它们也保留事务记录,这应该不会太难。您还可以每隔几个小时左右添加一个定期任务,将库存级别备份到事务表中,这样即使错过了一个事务,也可以发现更改何时发生或回滚到以前的状态。

如果你想知道一个大型应用程序是如何看待 SugarCRM的,他们有和库存管理模块,尽管我不确定它是如何存储数据的。

我可以看到使用两个列的一些好处,但是我没有理解关于差异的部分——您似乎在暗示,使用两个列(内部和外部)比使用单个列(当前)更不容易产生差异。为什么?

视乎情况而定,两者均属有效。如符合下列条件,前者为最佳:

  • 要求加总的项目数量相对较少
  • 很少或根本没有例外情况需要考虑(回报、调整等)
  • 库存物品的数量不是经常需要的

另一方面,如果你有大量的项目,几个例外的情况下,经常访问,这将是更有效的维护项目数量

还要注意,如果你的系统有差异,那么 里面有虫子应该被跟踪和消除

我已经做了系统两种方式,两种方式都可以很好地工作-只要你不忽视的错误!

我认为这实际上是一个通用的最佳实践问题,即在每次需要总计数时进行(相对)昂贵的计数,而在每次事情发生变化时进行计数,然后将计数存储在一个字段中,并在需要总计数时读取该字段。

如果不能使用事务,那么每次需要总计时,我都会使用活动计数。如果事务是可用的,那么在同一个事务中执行库存更新操作和保存重新计算的总数将是安全的,这将确保计数的准确性(尽管我不确定这对于多个用户访问数据库是否有效)。

但是,如果性能真的不是一个大问题(而且现代数据库在计数行方面做得足够好,我甚至很少担心这个问题) ,那么每次我都会坚持实时计数。

没有一个或两个专栏,我的意思是“总库存收到-总库存出售”是这样的东西:

Select sum(quantity) as inventory_received from Inventory_entry
Select sum(quantity) as inventory_sold from Sales_items

那么

Qunatity_on_hand = inventory_received - inventory_sold

请记住,我过分简化了这一点和我的初步解释。我知道有更多的存货,只是保持数量的轨道,但在这种情况下,这是问题的谎言,我们想解决什么。在这一点上,改变它的原因正是支持当前设计引起的问题的成本。

我还想提到的是,虽然这不是一个“编码”的问题是相关的算法和设计,其中 IMHO 是非常重要的主题。

谢谢大家到目前为止的回答。

Nelson Marmol

我们解决不同的问题,但我们解决其中一些问题的方法可能会让你感兴趣。

我们允许系统进行“最佳猜测”,并定期向用户反馈任何看起来错误的猜测。

要将此应用于库存,可以有3个字段:

inventory_received
inventory_sold
estimated_on_hand

然后,您可以按以下方式运行一个流程(每天?) :

SELECT *
FROM   Inventory
WHERE  estimated_on_hand != inventory_received - inventory_sold

当然,这取决于用户查看这个警报并对其做些什么。

此外,您还可以有一个函数来以某种方式重置库存,或者通过更新库存 _ sell/ 或添加另一个字段“库存调整”,这个字段可以是正的,也可以是负的。

只是一些想法,希望能有所帮助。

我以前研究过解决这个问题的系统。我认为理想的解决方案是一个预先计算的列,它可以让你两全其美。您的 total 将是一个字段,因此没有昂贵的查找,但它不能与其余数据失去同步(数据库保持完整性)。我不记得哪些 RDMS 支持预计算列,但是如果您没有事务,那可能也不可用。

您可以使用触发器潜在地伪造预计算列(非常有效... 我看不出有什么缺点)。不过,您可能需要进行交易。恕我直言,在进行这种受控的反规范化时,保持数据完整性是触发器的唯一合法用途。