2012-06-07 4 views
0

У меня есть таблица счетов, которая имеет основной ключ InvoiceID (int identity). и столбцом InvoiceNumber, который является межсетевым. У меня есть другая таблица, которую я использую для создания номера счета-фактуры Invoice_Numbers (см. Ниже). Чтобы убедиться, что номер счета является уникальным и предотвратил пробелы, я выполнил приведенный ниже код. Может ли кто-нибудь просмотреть этот код и прокомментировать его надежность. Запуск SQL 2008 в многопользовательской среде.Последовательные номера счетов SQL-сервер

Каковы шансы получения пользователями одинакового номера счета, когда они звонят тогда, при прокладке счетов?

 
IF EXISTS 
    (SELECT * 
    FROM sys.objects 
    WHERE object_id = OBJECT_ID(N'[Imports].[Invoices_Numbers]') 
      AND type IN (N'U')) 
    DROP TABLE [Imports].[Invoices_Numbers]

GO

CREATE TABLE [Imports].[Invoices_Numbers] ( [InvoiceNumber] [INT] IDENTITY(1, 1) NOT NULL ,[Deleted] [BIT] NOT NULL ,[Used] [BIT] NOT NULL, CONSTRAINT [PK_Invoices_Numbers] PRIMARY KEY CLUSTERED ([InvoiceNumber] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

GO

ALTER PROCEDURE [Imports].[Get_Invoice_Number] ( @InvoiceNumber INT OUTPUT ) AS BEGIN DECLARE @NewNumber INT DECLARE @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

END

+1

См SO вопрос [Как бы вы реализуете последовательности в Microsoft SQL Server?] (http://stackoverflow.com/q/282943/880990) –

+0

Gareth вы не читали сообщение полностью –

+0

Оливье только что перешел по ссылке. Однако он не затрагивает ключевые проблемы, которые я пытаюсь решить. Сначала среда является многопользовательской, поэтому возможность proc. называется одновременным. Второй im использует вторую таблицу для генерации номеров счетов (последовательно), где я гарантирую, что что-то пошло не так, пробелы заполнены. Присмотритесь к proc. и посмотреть, что я пытаюсь сделать. –

ответ

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 
+0

Выглядит более элегантно. Позвольте мне попробовать ваш подход и сообщит вам –

+0

Спасибо большое отлично работает и не обеспечивает пробелов. Я сделал образец стола и попробовал немного скручивания и поворота, и это, казалось, дало мне именно то, что мне нужно. еще раз спасибо!!! –

+3

Просто добавьте для тех, кто будет использовать этот подход. Вы должны убедиться, что вы не удаляете счета-фактуры, так как это создаст проблему, поскольку числа, которые вы получаете, основаны на подсчете строк. Я предпочел отмечать удаленные фактуры, а не удалять их. –

Смежные вопросы