我创建了一个库存控制数据库,其中包含两个表(实际上超过两个,但这些是与我的问题相关的两个表):库存和收据
我希望库存表中的库存与收据表中的库存之间的链接更加清晰,如果客户每张收据只能订购一件库存,那就没问题,因为我&# 39; d只需在Recipts表中有一个StockID列和Quantity列,StockID列为Stock表中ID的FK,但是,客户可以在其上创建包含任意数量库存的收据,这意味着我必须在收据表中包含大量列(即StockID_1,Quantity_1,StockID_2,Quantity_2等)
有没有办法解决这个问题(你有没有在MySQL中有一个动态扩展的列集),除了我目前所做的,就是拥有一个具有以下结构的OrderContents列(数据库或其他任何内容不强制执行)StockID1xQuantity,StockID2xQuantity等等?
我会发布数据库结构的图像,但我还没有足够的重复。通过将数据库规范化为第4或第5范式,我的讲师提到了可以做到的事情吗?
答案 0 :(得分:1)
我建议有3张桌子:
股票(StockID)+特定股票字段
收据(收据ID)+收据特定字段。
StockReceipt (收据ID,StockID,数量)(可以有StockReceiptID,或使用StockID + ReceiptID作为主键)
包含价格的解决方案可能如下:
股票(股票代码,价格)
PriceHistory (StockID,Price,Date)或(DateFrom,DateTo)
收据(ReceiptID,ReceiptDate)
StockReceipt (收据ID,StockID,数量)
这样您就可以计算过去任何收据的TotalStockReceiptPrice和TotalReceiptPrice。
我怀疑可能正是您正在寻找的东西:
股票(StockID,StockPrice)
收据(收据ID)
StockReceipt (收据ID,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
这一切都非常规范化(再次,不知道正常形式 - 第3?)。但是,只有当Stock Record上的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
)很可能已经知道价格,因此可以插入价值。
答案 1 :(得分:0)
不,关系数据库不允许动态列。关系表的定义是它有一个标题列的标题,每个行都有相同的列。
重复库存列组的技术违反了First Normal Form,并且还存在许多实际问题,例如:
最简单的解决方案是@OGHaza描述的,在另一个表中的行上存储额外的库存/数量数据。这样就解决了上述问题。
如果你真的想要理解关系概念,那么一本易于阅读的好书是:{J. 3。}来自C. J. Date。
在某些情况下,您希望使用不重复的动态列扩展表定义 - 它们只是新属性。这不是关系,但并不意味着我们不需要一些数据建模技术来处理您描述的场景。
对于此类问题,您可能希望阅读我的演示文稿SQL and Relational Theory: How to Write Accurate SQL Code,了解不同解决方案的概述及其优缺点。
PS:第四和第五范式与此方案有 nothing 。你的讲师显然不理解他们。