NOTE : If there is similar question, please refer me to it.
I have two tables Request
& Receipt
.
I want table Receipt
remain locked for CRUD operations from anywhere until transaction finished. I need the transaction be in a Stored Procedure.
Is it impossible? How?
Why should Receipt
remain locked?
Cause an internal request for insert or delete Receipt
will be unable to manipulate it! Note that I need ReceiptId
's be consecutive per each Request
from its start
, to its finish
!
Best Answer
Use a key table to allocate receipt numbers in a way that is concurrency friendly, and still guarantees receipt numbers will never be re-used, and will (almost) never contain gaps.
I've created a minimally complete verifiable example that you could use as a basis for learning about concurrency that should set you on a good path.
Do this work in tempdb so we don't kill anything important in your actual work:
If the objects we're creating already exist, then we'll delete them first. This allows us to easily modify the code below and re-run it multiple times for testing.
Requests table - add columns as required:
Receipts table. ReceiptID is generated by the system, ReceiptNum is the number we'll show to users.
The Key table, where we store the most recently allocated ReceiptNum value:
The CreateRequests stored procedure:
Here, we add three different requests, with a varying number of receipts to show the functionality of the stored procedure:
The output:
Run #2:
The output:
Run #3:
The output:
To verify concurrency, and that the allocation of Receipt Numbers is reliable, I ran the following code simultaneously in three separate SSMS windows, creating nearly 30,000 receipts: