I need to increment an integer in a SQL Server 2008 column.
Sounds like I should use an IDENTITY
column, but I need to increment separate counters for each of my customers. Think of an e-commerce site where each customer gets their own incrementing order number, starting with 1. The values must be unique (per customer).
For example,
Customer1 (Order #s 1,2,3,4,5...) Customer2 (Order #s 1,2,3,4,5...)
Essentially, I will need to manually do the work of SQL's identity
function since the number of customers is unlimited and I need order #
counters for each of them.
I am quite comfortable doing:
BEGIN TRANSACTION SELECT @NewOrderNumber = MAX(OrderNumber)+1 From Orders where CustomerID=@ID INSERT INTO ORDERS VALUES (@NewOrderNumber, other order columns here) COMMIT TRANSACTION
My problem is locking and concurrency concerns and assuring a unique value. It seems we need to lock with TABLOCKX
. But this is a high volume database and I can't just lock the whole Orders
table every time I need to do a SELECT MAX+1
process and insert a new order record.
But, if I don't lock the whole table, then I might not get a unique value for that customer. Because some of our order entry is done after-the-fact in batches by a multi-threaded Windows process, it is possible that 2 operations will be simultaneously wanting to insert a new order for the same customer.
So what locking methodology or technique will avoid deadlocks and still let me maintain unique incrementing order numbers PER customer?
Each time a row is inserted into the table, the identity column is assigned the next highest value. If the identity reaches the maximum value, inserts will fail.
In SQL Server 2012 - MS had introduced 'Identity Cache'. This feature had a bug of auto-incrementing ID column by '1000'. For example, if ID columns are 1, 2 and when an ID Jump happens the next ID column is 1003, instead of '3'. There are workarounds available to fix this issue.
In SQL Server 2005 and later, this is best done atomically, without using any transactions or locking:
update ORDERS set OrderNumber=OrderNumber+1 output inserted.OrderNumber where CustomerID=@ID
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With