Reputation: 1982
I have the following stored procedure. It is meant to get a name. If the name exists in a table it returns its corresponding ID. If it doesn't exist yet, it creates a new ID, and adds it to the table with the new ID.
The problem is that when I run this on multiple threads which use the same name (not yet in the table) I sometimes get the name entered several times, with subsequent IDs.
What I would like is for the transactions to block while another transaction is running, so that the name only gets in the database once.
Is there an isolation level or select hint I should be using? Is there another way to do this?
CREATE PROCEDURE [dbo].[sp_createID]
@name varchar(max)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRAN
DECLARE @id as int
SELECT @id=Id FROM MyTbl WHERE name=@name
IF @id IS NULL
BEGIN
UPDATE idGeneratorTbl SET lastkey=lastkey+1
SELECT @id=lastKey FROM idGeneratorTbl
INSERT INTO MyTbl VALUES(@id, @name)
END
SELECT @id
COMMIT
END
Upvotes: 2
Views: 1353
Reputation: 36176
Both of the procs should be on the same transaction to achieve what you want.
You can achieve that by removing the transaction control in the [sp_generateNewId] proc.
FYI, you don’t need to worry about keys generation, why don’t you just create an IDENTITY field
Upvotes: 1