【问题标题】:Sequential Invoice Numbers SQL server顺序发票编号 SQL 服务器
【发布时间】:2012-06-11 11:23:33
【问题描述】:

我有一个具有 InvoiceID (int identity) 主键的发票表。和一列 InvoiceNumber,它是一个整数。我有另一个表用于生成名为 Invoice_Numbers 的发票编号(见下文)。为了确保发票号码是唯一的并防止出现空白,我实施了以下代码。有人可以查看此代码并评论其可靠性。在多用户环境中运行 SQL 2008。

用户在插入发票时拨打电话然后购买时获得相同发票编号的可能性有多大?

如果存在 (选择 * FROM 系统对象 WHERE object_id = OBJECT_ID(N'[Imports].[Invoices_Numbers]') 并输入(N'U')) DROP TABLE [Imports].[Invoices_Numbers]

CREATE TABLE [Imports].[Invoices_Numbers] ( [InvoiceNumber] [INT] IDENTITY(1, 1) 非空 ,[已删除] [BIT] 非空 ,[已使用] [BIT] 不为空, 约束 [PK_Invoices_Numbers] 主键集群([InvoiceNumber] ASC)与(PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)ON [PRIMARY] ) 在 [主要]

ALTER PROCEDURE [Imports].[Get_Invoice_Number] ( @InvoiceNumber INT 输出 ) 作为 开始 声明 @NewNumber INT 声明 @MinNumber INT

BEGIN TRAN SELECT @MinNumber = MIN(InvoiceNumber) FROM Imports.Invoices_Numbers IF @MinNumber > 1 BEGIN SET IDENTITY_INSERT Imports.Invoices_Numbers ON; INSERT Imports.Invoices_Numbers ( Invoicenumber ,Deleted ,Used ) VALUES ( 1 ,0 ,1 ) SET IDENTITY_INSERT Imports.Invoices_Numbers OFF; SET @NewNumber=1 END ELSE BEGIN WITH Gaps AS (SELECT TOP 1 a.InvoiceNumber + 1 AS GapValue FROM Imports.Invoices_Numbers a WHERE NOT EXISTS (SELECT * FROM Imports.Invoices_Numbers b WHERE b.InvoiceNumber = a.InvoiceNumber + 1) AND a.InvoiceNumber < (SELECT MAX(InvoiceNumber) FROM Imports.Invoices_Numbers)) SELECT @NewNumber = GapValue FROM Gaps IF @NewNumber IS NULL BEGIN SELECT TOP 1 @NewNumber = InvoiceNumber FROM Imports.Invoices_Numbers WHERE Used = 0 AND Deleted = 0 ORDER BY InvoiceNumber IF @NewNumber IS NULL BEGIN INSERT Imports.Invoices_Numbers ( Deleted ,Used ) VALUES ( 0 ,1 ) SELECT @NewNumber = SCOPE_IDENTITY () END ELSE BEGIN UPDATE Imports.Invoices_Numbers SET Used = 1 WHERE InvoiceNumber = @NewNumber END END ELSE BEGIN SET IDENTITY_INSERT Imports.Invoices_Numbers ON; INSERT Imports.Invoices_Numbers ( Invoicenumber ,Deleted ,Used ) VALUES ( @NewNumber ,0 ,1 ) SET IDENTITY_INSERT Imports.Invoices_Numbers OFF; END END SELECT @InvoiceNumber = @NewNumber COMMIT TRAN

结束

【问题讨论】:

  • Gareth 你还没有完整阅读这篇文章
  • Olivier 刚刚浏览了该链接。然而,它并没有解决我试图解决的关键问题。首先,环境是多用户的,因此可能会出现 proc。被同时调用是有的。第二个即时消息使用第二个表生成发票编号(串行),我确保如果出现问题,空白被填补。仔细查看proc。看看我想做什么。
  • 公平点。我已删除该评论。如果您将 UNIQUE CONSTRAINT 添加到您的 InvoiceNumber 列,您将防止重复。
  • “序列”一词似乎让所有人望而却步。这个问题与会计有关——发票号、订单号、抽奖券号等需要分发给多个并发用户,并且会计师需要知道每个用户发生了什么和他们每一个人。 通常认为有必要按顺序发布它们(因此,没有间隙),但这实际上取决于应用程序。

标签: sql sql-server sql-server-2008


【解决方案1】:

您的解决方案看起来有点复杂。除了数据导入任务,我不建议将 set identity_insert 用于其他任何任务。

为了确保唯一性,我先添加一个唯一性约束:

alter table Invoices add constraint UX_Invoices_InvoiceNr unique

然后您可以使用这样的 SQL 语句插入发票:

while 1=1
    begin        
    declare @new_nr int
    select  @new_nr = max(InvoiceNr) + 1
    from    dbo.Invoices

    if @new_nr is null
        set @new_nr = 1

    insert  dbo.Invoices
            (InvoiceNr, ...)
    values  (@new_nr, ...)

    if @@rowcount = 1
        break
    end

【讨论】:

  • 看起来更优雅。让我试试你的方法,然后告诉你
  • 非常感谢,效果很好,确保没有间隙。我做了一个样品表并尝试了一些扭曲和转动,它似乎正好给了我我需要的东西。再次感谢!!!
  • 只是为任何将使用此方法的人添加。您必须确保不要删除发票,因为这会产生问题,因为您获得的数字是基于行数的。我选择将发票标记为已删除,而不是实际删除它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
  • 2012-08-11
  • 2016-07-01
  • 2010-12-21
  • 1970-01-01
  • 2014-10-25
相关资源
最近更新 更多