我需要生成发票的渐进编号,避免序列中出现空白:
一开始我以为这很容易
SELECT MAX(Docnumber)+1 as NewDocNumber
from InvoicesHeader
但是由于构建“插入InvoiceHeader”查询需要花费一些时间,并且另一个请求可能到达,因此为两个发票分配了相同的NewDocNumber
我现在正在考虑避免在高级查询和更改后的查询中生成DocNumber:
INSERT INTO InvoicesHeader (InvoiceID,..., DocNumber,...)
SELECT @InvoiceID,..., MAX(Docnumber)+1,... FROM InvoicesHeader
但是,尽管(它应该)解决了一些问题,但是它仍然是线程不安全的,并且不适合竞争条件:
以这种方式添加TABLOCK
或UPDLOCK
:
BEGIN TRANSACTION TR1
INSERT INTO InvoicesHeader WITH (TABLOCK)
(InvoiceID,..., DocNumber,...)
SELECT @InvoiceID,..., MAX(Docnumber)+1,... FROM InvoicesHeader
COMMIT TRANSACTION TR1
会解决这个问题吗?
或者更好地使用ISOLATION LEVEL
,NEXT VALUE FOR
或其他解决方案?
答案 0 :(得分:0)
您已经在SQL Server中具有线程安全的序列生成生成。了解有关Create Sequence的信息。从SQL Server 2012开始可用。最好在事务范围之外生成序列。
序列号在当前范围之外生成 交易。无论交易是否使用 序列号已提交或回滚。
您可以从序列中获取下一个值。我们一直在使用序列来生成订单号,但是当并行生成多个订单数字时,我们还没有发现问题。
SELECT NEXT VALUE FOR DocumentSequenceNumber;
已更新,根据注释,如果您有四种不同的文档类型,建议您先生成序列,然后再与特定的文档类型连接。您会更容易理解。在年底,您可以使用ALTER SEQUENCE
重新启动序列RESTART [WITH]将由返回的下一个值 序列对象。如果提供,则RESTART WITH值必须为 小于或等于最大值且大于或等于的整数 等于序列对象的最小值。如果WITH值 省略,序列号将根据原始编号重新开始 创建序列选项。