【问题标题】:Can I create a table structure with dynamic columns in MySQL?我可以在 MySQL 中创建具有动态列的表结构吗?
【发布时间】:2013-11-19 16:24:16
【问题描述】:

我创建了一个库存控制数据库,其中包含两个表(实际上不止两个,但这些是与我的问题相关的两个):库存和收据

我希望 stock 表中的库存和收据表中的库存之间的链接更清晰一点,如果客户每张收据只能订购一件库存,这会很好,因为我' d 只在 Recipts 表中有一个 StockID 列和一个 Quantity 列,StockID 列作为 Stock 表中 ID 的 FK,但是,客户可以在其上创建包含任意数量的库存项目的收据,这将意味着我必须在 Receipts 表中有大量列(即 StockID_1、Quantity_1、StockID_2、Quantity_2 等)

除了我目前所做的之外,有没有办法在 MySQL 中解决这个问题(你可以在 MySQL 中拥有一组动态扩展的列),即拥有一个具有以下结构的 OrderContents 列(其中不是由数据库或任何东西强制执行的)StockID1xQuantity、StockID2xQuantity 等等?

我会发布数据库结构的图像,但我还没有足够的声誉。我的讲师提到了可以通过将数据库规范化为第 4 或第 5 范式来完成的事情?

【问题讨论】:

    标签: mysql sql database multiple-columns


    【解决方案1】:

    我建议有 3 张桌子:

    股票 (StockID) + 股票特定字段

    收据(收据ID)+收据特定字段。

    StockReceipt(ReceiptID、StockID、Quantity)(可以有 StockReceiptID,或使用 StockID+ReceiptID 作为主键)


    包含价格的解决方案可能如下所示:

    库存(StockID、价格)

    PriceHistory(StockID、Price、Date)或(DateFrom、DateTo)

    收据(ReceiptID、ReceiptDate)

    StockReceipt(ReceiptID、StockID、数量)

    这样您就可以计算过去任何收据的 TotalStockReceiptPrice 和 TotalReceiptPrice。


    我怀疑这可能就是你要找的东西:

    股票(StockID、StockPrice)

    收据(收据ID)

    StockReceipt(ReceiptID、StockID、数量)

    SELECT r.ReceiptID, SUM(s.StockPrice * sr.Quantity) AS ReceiptPrice
    FROM Receipt r
    INNER JOIN StockReceipt sr ON r.ReceiptID = sr.ReceiptID
    INNER JOIN Stock s ON sr.StockID = s.StockID
    GROUP BY r.ReceiptID
    

    这一切都非常规范化(再次,不知道什么正常形式 - 3rd?)。但是,它仅在 Stock 记录上的 StockPrice 永不更改时才有效。一旦它发生变化,您的 ReceiptPrices 将全部反映新价格,而不是客户实际支付的价格。

    如果价格可以更改,您需要保留价格历史表(ItemID、Price、DateTo、DateFrom)或在 StockReceipt 记录中记录 StockPrice(然后将 JOIN 删除到 Stock在上面的查询中记录并使其使用sr.StockPrice而不是s.StockPrice)

    要执行您在下面发布的INSERT,您必须执行以下操作:

    INSERT INTO StockReceipts  (ReceiptID, StockID, Quantity, TotalStockPrice) 
    SELECT 1, 99, 2, s.StockPrice
    FROM Stock s 
    WHERE s.StockID = 99
    

    但是很可能发出这张收据(并触发INSERT)的任何东西都已经知道价格,因此可以插入该值。

    【讨论】:

    • 这是对数据库进行规范化,但我无法告诉你是什么规范形式。
    • 这可能行得通,谢谢 :) 将 StockID+ReciptID 作为复合主键是有意义的。
    • 这是标准的第三范式,一个常规的多对多关系。一份库存物品可以在多张收据上,一张收据可以包含许多库存物品。
    • @nielsm,谢谢你的信息,这些天我真的需要回去阅读规范化
    • 是否符合(如果我使用 StockReceipt 表)在 Recipts 表中的整个订单的 Total Price 列,以及 StockRecipt 表中的 TotalStockPrice 列,它存储该库存商品的总价是多少?
    【解决方案2】:

    不,关系数据库不允许动态列。关系表的定义是它有一个表头来命名列,并且每一行都有相同的列。

    你重复股票列组的技术是违反第一范式的,它也有很多实际问题,例如:

    • 您怎么知道要创建多少额外的列?
    • 当您不知道给定值在哪一列时,如何搜索它?
    • 如何实现唯一性?

    最简单的解决方案是如@OGHaza 所述,将 上的额外库存/数量数据存储在另一个表中。这样就解决了上面的问题。

    • 您不需要创建额外的列,只需创建额外的行,使用 INSERT 很容易。
    • 您可以在 one 列中搜索给定值以找到它。
    • 您可以对列设置约束。

    如果你真的想了解关系概念,一本好读的好书是:SQL and Relational Theory: How to Write Accurate SQL Code C. J. Date。


    在某些情况下,您希望使用不重复的动态列来扩展表定义——它们只是新属性。这不是关系型,但这并不意味着我们不需要一些数据建模技术来处理您描述的场景。

    对于此类问题,您可能想阅读我的演示文稿Extensible Data Modeling with MySQL,了解不同解决方案的概述及其优缺点。


    PS:第四和第五范式与这种情况无关。你的讲师显然不理解它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-26
      • 2021-04-07
      • 1970-01-01
      • 2015-04-19
      • 2018-06-28
      • 2019-06-15
      • 1970-01-01
      相关资源
      最近更新 更多