这是一个理论情景,
假设我有一个客户表和一个发票表。 1个客户可以有很多发票。
现在我希望每张发票都有一个该客户独有的发票号
即
ClientId InvoiceNo
1 IN0001
2 IN0001
2 IN0002
2 IN0003
3 IN0001
目前我通过查看最大值等来控制我的应用程序,但这显然不是一个很好的解决方案。我更愿意让我的数据库为我这样做,因为它应该消除为单个客户创建重复的发票号码的风险(竞争条件?)
我一直在阅读Sql Server 2012的SEQUENCE,这听起来很棒,但问题是我仍然需要每个客户端单独的序列
即。
CREATE SEQUENCE InvoiceNum_Client1.....
CREATE SEQUENCE InvoiceNum_Client2.....
CREATE SEQUENCE InvoiceNum_Client3.....
但每次创建新客户端时,从我的应用程序中进行db meta更改都会让人觉得非常脏。此外,我的触发器必须做这样的事情(我甚至不知道该怎么做)
NEXT VALUE FOR InvoiceNum_Client + @ClientId
等
所以我的下一个想法是有一个“序列”表,即
ClientID INSequenceNumber
1 1
2 3
3 3
在我的触发器中获取给定客户端的InSequenceNumber,使用它来生成invoiceNumber,然后更新序列表,为同一客户端递增InSequenceNumber 1。它应该具有相同的效果,但我只是不确定交易和范围等的内部运作方式
所以我的问题是
谢谢!
答案 0 :(得分:1)
是否有特定原因要求发票编号仅对每个客户而言是唯一的?在大多数ERP系统中,发票编号通常是全球唯一的,使实施更加容易。无论如何,你应该有一个包含主键的Invoice表(你不应该使用复合主键 - 这只是简单的坏数据建模)。
这给我们留下了一个场景,您可能根本不需要在数据库中存储“per-client-invoice-number”。假设您有一个名为“Invoices”的表,其中包含以下数据:
Id | ClientId
---------------
1 | 1
2 | 1
3 | 2
4 | 1
5 | 3
6 | 2
此处,Id
是发票表的主键,而ClientId是外键。像这样的查询:
SELECT
ClientId,
'IN' + RIGHT('0000' +
CONVERT(VARCHAR, ROW_NUMBER() OVER (PARTITION BY ClientId
ORDER BY Id)) AS InvoiceNo,
Id
FROM Invoices
ORDER BY ClientId, InvoiceNo
会回来:
ClientId | InvoiceNo | Id
---------------------------
1 | IN0001 | 1
1 | IN0002 | 2
1 | IN0003 | 4
2 | IN0001 | 3
2 | IN0002 | 6
3 | IN0001 | 5
答案 1 :(得分:0)
为什么客户必须拥有自己的序列?有一个全局序列号。然后,如果要按顺序获取客户端序列,请使用row_number()
:
select i.*, row_number() over (partition by clientid order by invoiceno) as ClientInvoiceSequence
from invoices;
注意:您可能希望order by
位于其他字段,例如日期。
如果您开始将此信息存储在数据库中,您将需要进行大量的簿记和谨慎的事务管理:
最好使用标识列并在需要时计算序列。