Database design 发票及;发票行:如何存储客户地址信息?

Database design 发票及;发票行:如何存储客户地址信息?,database-design,invoices,Database Design,Invoices,嗨,我正在开发一个发票应用程序 因此,总体思路是有两个表: Invoice (ID, Date, CustomerAddress, CustomerState, CustomerCountry, VAT, Total); InvoiceLine (Invoice_ID, ID, Concept, Units, PricePerUnit, Total); 正如您所看到的,这种基本设计会导致大量重复记录,其中客户将拥有相同的地址、州和国家 因此,另一种选择是创建一个地址表,然后创建一个关系地址

嗨,我正在开发一个发票应用程序

因此,总体思路是有两个表:

Invoice (ID, Date, CustomerAddress, CustomerState, CustomerCountry, VAT, Total);

InvoiceLine (Invoice_ID, ID, Concept, Units, PricePerUnit, Total); 
正如您所看到的,这种基本设计会导致大量重复记录,其中客户将拥有相同的地址、州和国家


因此,另一种选择是创建一个地址表,然后创建一个关系地址,我强烈建议不要在发票中存储任何这样的客户详细信息

相反,我的结构如下:

Customer表,主键为id

客户地址表(随着时间的推移,每个客户可能有不同的地址),客户id作为外键

发票表,其地址字段是客户地址表的外键


大多数标准产品/订单数据库都有

a products table (ProductId, product info fields)  
a customers table (CustomerID, customer info like address etc) 
and an orders table  (OrderNumber, CustomerID, date, etc)
然后,您的订单项成为订单和产品之间的多个关系表

orderItems (OrderNumber, ProductID, quantity, purchasePrice, vat, etc)

要获取完整发票,您需要查询orders表并将其与OrderItems表联接。Orror项目通常有购买价格,因为产品订单中的价格在订单创建后可能会发生变化,而且信息通常是有用的。

< P>我会考虑用三个表来做:<代码>客户>代码>,代码>发票< /代码>和<代码>地址>代码>,但是构造它以便一旦地址进入,它从不更新或删除,只是不推荐使用。地址表中可以有一个
IsDeprecated
IsActive
布尔字段。然后,当您创建发票时,发票链接到CustomerID和当时使用的AddressID。当客户更改其地址时,您将使用新的AddressID创建一个新记录,并使用布尔字段弃用旧记录。或者,如果您真的想保持良好的记录和/或需要查找此数据,您可以使用
AddressActiveStartDate
AddressActiveEndDate
,但这会使查询变得更复杂

这样,您仍然可以存储旧地址,并将其链接到客户以供参考,同时还允许客户拥有多个列出的地址(例如,一个用于发货,一个用于计费)


您可以根据需要添加更多表格,例如,
产品
发票行
状态
,等等。

您不认为发票表格几乎与历史表格相似,因此重复发票最初打印方式的信息是有效的吗?@elviejo,可以说您是正确的,但是,您必须评估是要反复存储相同的信息,还是只存储所用地址的外键。如果存储外键,则意味着一旦发票链接到它,就不能更改旧地址,相反,任何更改都必须成为新的地址记录,您只需在地址表上维护一个标志,指示地址是否处于活动状态。@elviejo您也可以这样做,而无需为客户更改整个地址维护过程。在订单成为发票时,您可以链接到客户实体和“匿名”地址实体(可能在“收货方”和“收货方”角色中),其中仅包含发票时的地址。您查找所有地址列并获得一个代理键。此“地址”历史记录从不更新,仅插入。以前的地址只是重复使用。这样,您就可以获得时间点数据,而不必改变整个客户维护设计。@uri在这个问题上:他们强调存储计算的增值税是一种很好的做法。我认为这个地址在同一个类别中会失败。也许这个问题没有明确的答案?@elviejo:我想你误解了我对增值税的看法。我的观点是增值税应该在商品层面,而不仅仅是整个发票层面。例如,在我的州(PA),我们在商店购买的每件商品都要缴纳不同的税。同时,在一家餐馆,我们向州政府(食品)缴纳不同的税,向城市(酒精)缴纳不同的税。我的观点是,为了更好地跟踪/核算,您可能希望在行项目级别而不是整个发票级别进行纳税。例如,如果有人退货,你需要偿还他们所付的费用。虽然我同意你的总体设计,但我过去曾因orderItems没有遵循标准化而受到批评,因为在productID、price、orderItems中有数千或数百万(数十亿?)相同的信息,等等。你如何解释这一点,或者这是一个规范化失败的例子?