【问题标题】:Need some suggestions for database design for Invoices in a multi-tenant app需要一些关于多租户应用程序中发票数据库设计的建议
【发布时间】:2015-11-17 08:51:35
【问题描述】:

我需要一些有关在多租户应用程序中设计发票架构的指导。 我有一个名为EmployeePay 的表,其中包含生成发票所需的所有信息。发票表将包含发票编号、发票创建日期和VAT 费率。我正在考虑为每个Tenant 创建一个Sequence 对象以生成发票编号。

EmployeePay Table: EmployeeID, Hours, Rate, InvoiceID (FK)

Invoice Table: InvoiceID (PK) (Identity), InvoiceNumber, InvoiceDate, VATRate, TenantID

是否可以在数据库中拥有数百个 Sequence 对象,因为我必须为每个租户创建一个?我还必须创建相同数量的存储过程来返回下一个发票编号(我更喜欢为每个租户使用一个单独的存储过程,而不是在一个 select case 语句中使用一个包含数百个选项的大型存储过程)。

另一个问题是,理论上是不是根据事务表(EmployeePay)插入主表(Invoice),然后使用其主键(InvoiceID)更新事务表?

提前致谢。

【问题讨论】:

  • 所以基本上你想要一个租户级别的 InvoiceNumber 系列......意味着如果我们为同一个租户生成第二张发票,那么它应该增加 1 ??
  • 没错,每个租户都应该有自己的一系列发票号码。
  • 我建议不要这样做。数据库对象的数量不应依赖于数据库用户的数量。有很多方法可以计算下一个发票编号,而无需为每个租户创建一个序列对象。
  • @ZoharPeled 我同意你的观点,但除了使用序列或有一个列并增加它之外,我真的想不出更好的解决方案。如果能多分享一些方法就好了。

标签: sql-server database database-design


【解决方案1】:

首先确保关系是一对多或多对多。如果您正在考虑一位将有许多发票的员工,那么它是一对多的关系,您可以创建如下表格:

EmployeePay Table: EmployeeID (PK) (Identity), Hours, Rate

Invoice Table: InvoiceID (PK) (Identity), EmployeeID (FK), InvoiceNumber, InvoiceDate, VATRate, TenantID

编辑:

我不知道您使用的是哪个数据库,但用于增量序列检查:

  1. 对于 MySQL,请检查此LINK
  2. 如果您使用的是 Oracle,请查看此LINK

【讨论】:

  • 我正在使用 SQL Server,它是一对多的关系,一张 Invoice 可以有许多 EmployeePay 详细信息。
  • 如果一张发票可能是employeePay,那么您创建的架构就可以了。应用它,如果有一名员工和许多发票,请按照我的指示进行。喜欢的话别忘了标记我的答案
【解决方案2】:

我建议您创建另一个可以称为 InvoiceNumber 的表,这将包含 InvoiceNumberId(Int)TenantId (Fk)CurrentSequenceNumber(Int )

CurrentSequenceNumber 的意义在于它将是一个简单的整数,可用于生成下一个 Invoicenumber。InvoiceNumberId 将是用于主键目的的标识列(您可能拥有也可能没有)。

表格的结构如下所示。

现在您只需要创建 一个 存储过程,它将输入参数作为 TenantId,并负责通过读取上表中的 CurrentSequenceNumber 来生成下一个发票编号。

例如,如果我们需要为 id 为 15 的租户生成新的 Invoice Id,那么 SP 将拥有您的业务逻辑是。

Inv-0009

然后在生成此编号后,SP 会将 InvoiceNumberId 3 的值增加到 9。

所以一切都将由单表和单程序管理。

【讨论】:

  • 在您的序列表中,为什么将 [InvoiceNumberId] 作为 PK?每个租户只有一个序列,所以使用它。而且这个序列不是一个“Id”,它只是一个数字。
  • @Tony ..你说得对,SequenceId 不是一个正确的名称,它只是一个数字,我将对其进行更新......此外,至少有两种方法可以获得主键。 1 是使用tenantId-SquenceId 作为复合主键或第二种方式有另一个身份列作为主键,我采取了第二种选择。
  • 也不需要复合键,[TenantId] 本身就足以作为 PK。
  • 我之前已经考虑过这种方法,但它可能会导致性能瓶颈 (stackoverflow.com/questions/1104741/…)。所以我决定改用序列对象,它可以非常巧妙地实现。
  • @Tony...是的,我同意你的看法。这将是更正确的设计。
猜你喜欢
  • 2010-10-18
  • 2014-01-27
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 1970-01-01
相关资源
最近更新 更多