Rya*_*ill 16 sql database database-design
前言:我前几天想到新应用程序的新数据库结构,并意识到我们需要一种以有效的方式存储历史数据的方法.我想让别人看一看,看看这个结构是否有任何问题.我意识到这种存储数据的方法很可能是之前已经发明的(我几乎可以肯定它已经发明)但是我不知道它是否有一个名字和一些谷歌搜索,我试过没有产生任何东西.
问题:假设您有一个订单表,订单与下订单的客户的客户表相关.在普通的数据库结构中,您可能会遇到以下情况:
orders
------
orderID
customerID
customers
---------
customerID
address
address2
city
state
zip
Run Code Online (Sandbox Code Playgroud)
非常简单,orderID有一个customerID的外键,它是customer表的主键.但是,如果我们要在订单表上运行报表,我们将把客户表加入订单表,这将返回该客户ID的当前记录.如果下订单时,客户地址不同并且随后更改了.现在,我们的订单不再反映订单下达时客户地址的历史记录.基本上,通过更改客户记录,我们只是更改了该客户的所有历史记录.
现在有几种解决方法,其中一种方法是在创建订单时复制记录.我想出的是我认为这样做的一种更简单的方法,可能更优雅一点,并且可以随时更改记录.
如果我做了这样的结构,那该怎么办:
orders
------
orderID
customerID
customerHistoryID
customers
---------
customerID
customerHistoryID
customerHistory
--------
customerHistoryID
customerID
address
address2
city
state
zip
updatedBy
updatedOn
Run Code Online (Sandbox Code Playgroud)
请原谅格式,但我认为你可以看到这个想法.基本上,我们的想法是,无论何时更改,插入或更新客户,customerHistoryID都会递增,customers表会使用最新的customerHistoryID进行更新.订单表现在不仅指向customerID(允许您查看客户记录的所有修订),还指向customerHistoryID,它指向记录的特定修订.现在,订单反映了订单创建时的数据状态.
通过将updatedby和updatedon列添加到customerHistory表,您还可以看到数据的"审核日志",以便您可以看到谁进行了更改以及何时进行更改.
一个潜在的缺点可能是删除,但我并不担心这种需要,因为任何事情都不应该被删除.但即便如此,使用activeFlag或类似的东西可以实现相同的效果,具体取决于数据的域.
我的想法是所有表都会使用这种结构.无论何时检索历史数据,都将使用customerHistoryID将其连接到历史表,以显示该特定订单的数据状态.
检索客户列表很简单,只需加入customerHistoryID上的customer表即可.
任何人都可以从设计的角度看待这种方法的任何问题,或者为什么这是坏的性能原因.请记住,无论我做什么,我都需要确保保留历史数据,以便后续记录更新不会更改历史记录.有没有更好的办法?这是一个已知的想法,有一个名称,或其上的任何文件?
谢谢你的帮助.
更新: 这是我真正想要的一个非常简单的例子.我真正的应用程序将有"订单"与其他表的几个外键.原点/目的地位置信息,客户信息,设施信息,用户信息等.有人建议我有几次可以将信息复制到订单记录中,我已经多次这样做了,但这会产生包含数百列的记录,在这种情况下实际上是不可行的.
Con*_*rix 10
当我遇到这样的问题时,另一种方法是将订单作为历史表.它的功能相同,但更容易理解
orders
------
orderID
customerID
address
City
state
zip
customers
---------
customerID
address
City
state
zip
Run Code Online (Sandbox Code Playgroud)
编辑:如果你喜欢的列数很高,你可以随意将它分开.
如果您使用其他选项并使用历史表,则应考虑使用双时态数据,因为您可能必须处理历史数据需要更正的可能性.例如,客户将其当前地址从A更改为B,但您还必须更正当前已完成的现有订单的地址.
此外,如果您使用的是MS SQL Server,则可能需要考虑使用索引视图.这将允许您交换小的增量插入/更新性能减少,以获得大的选择性增加.如果您不使用MS SQL服务器,则可以使用触发器和表来复制它.
在设计数据结构时,要非常小心地存储正确的关系,而不是类似于正确关系的关系.如果需要维护订单的地址,那么这是因为地址是订单的一部分,而不是客户.此外,单价是订单的一部分,而不是产品等.
尝试这样的安排:
Customer
--------
CustomerId (PK)
Name
AddressId (FK)
PhoneNumber
Email
Order
-----
OrderId (PK)
CustomerId (FK)
ShippingAddressId (FK)
BillingAddressId (FK)
TotalAmount
Address
-------
AddressId (PK)
AddressLine1
AddressLine2
City
Region
Country
PostalCode
OrderLineItem
-------------
OrderId (PK) (FK)
OrderItemSequence (PK)
ProductId (FK)
UnitPrice
Quantity
Product
-------
ProductId (PK)
Price
etc.
Run Code Online (Sandbox Code Playgroud)
如果您确实需要存储某些内容的历史记录,例如跟踪订单随时间的变化,那么您应该使用日志或审计表,而不是使用事务表.