0

I have an SQL Server table where I store invoices lets call it invoice. I need to implement a continuous autonumber feauture for invoices (not the autoidentity which is not continuous). Moreover I should take care of concurrency issues for example user A and user B invoice the same time but the two invoices should not have the same number (obviously).

What would be an ideal implementation method in T-SQL?

Ioannis
  • 509
  • 2
  • 6
  • 12
  • If I didnt have to use identity column? – Ioannis Aug 03 '11 at 11:58
  • My understaing is, SQL Server IDENTITY columns are implemented the way they are because of the two more or less equally important issues in view: concurrency and performance. You are guaranteed to have unique values because of the former, but you have to put up with possible gaps because of the latter. Now you are trying to eliminate the possibility of gaps (in your own implemenation of IDENTITY). What do you think you are going to suffer from in return? – Andriy M Aug 03 '11 at 12:02
  • I am wasnt very clear... For example the last invoice has the number 190 and I delete the invoice #32. Then the new inserted invoice would need to have number 32. Thats the reason i dont need identity. – Ioannis Aug 03 '11 at 12:02
  • 2
    should you really be re-using invoice numbers? I wouldn't.... – Mitch Wheat Aug 03 '11 at 12:10
  • this is a legislation issue in the case of deleted invoices. – Ioannis Aug 03 '11 at 12:14
  • 1
    legislation that allows invoices with lower numbers to have later dates....? – Mitch Wheat Aug 03 '11 at 12:17
  • Related: http://stackoverflow.com/questions/3845450/insert-data-in-to-sql-server-data-table/3845543#3845543 – Martin Smith Aug 03 '11 at 23:12

4 Answers4

2

An IDENTITY column.

If you need an invoice number that is alphanumeric I suggest you update your question with the required format.

There will only be gaps if you delete records, experience an error during an INSERT, rollback a transaction that contain an INSERT(s) into the table, or the seed is updated by a relevant dbcc command.

If you really have to reuse gaps (and I certainly wouldn't do so for things like invoices, for instance, in your example invoice #32 would have a later date then invoice #190 ...): then you could, in a serializable transaction, find lowest free value, set identity insert on, insert a row with that Id value, and then set identity insert off and commit the transaction.

Something like this (untested):

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

BEGIN TRAN
SET IDENTITY_INSERT dbo.myTable ON

DECLARE @minId int = -1

;WITH cterows(Id, rownum)
AS
(
   SELECT Id, row_number() OVER(ORDER BY Id ASC) AS rownum 
)
SELECT @minId = MIN(rownum) FROM cterows
WHERE Id <> rownum

IF (@minId IS NOT NULL AND @minId <> -1) 
   BEGIN
     -- found a gap
     -- Insert at @minId
   END
ELSE
   BEGIN
     -- No gap, INSERT as normal
   END


SET IDENTITY_INSERT dbo.myTable OFF;
COMMIT
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
2

One way we did something similar was to create a table called useID with only one column called [ID]. We use an Integer data type for it. This table also only has one row. More on that in a bit.

Now, each time we need to log an event we SELECT from useID and run our transaction with this [ID] value being used for tracking purposes. Right after we have SELECTed the [ID] we increment the value in useID by 1 (or whatever we need for the system in question). In this way we maintain unique and contiguous [ID] values. We can delete from the destination of the [ID] value without affecting the order of the new [ID] values. Performance on this is very good as we run ~10million transactions a night using this and we do reset the starting value every 3 months or so since we do not keep items 'live' that long.

wergeld
  • 14,332
  • 8
  • 51
  • 81
1

If it isn't necessary these numbers to be continues, you can create random number,but if it should be continues you can make that column IDENTITY colunm

check this post to create your random number

Amir Ismail
  • 3,865
  • 3
  • 20
  • 33
0

You can make a SQL Varchar column for alphanumeric invoice number, Here you need to generate unique invoice no or can use IDENTITY column.

Pankaj Agarwal
  • 11,191
  • 12
  • 43
  • 59