I have a stored procedure that inserts a row into a table if the row key doesn't already exist. It looks like this:
create proc EmployeeInsertIfNotExists
(@id int, @name varchar(50))
as
begin
SET XACT_ABORT ON
begin transaction
if not exists(select * from tbl where id = @id)
insert into tbl(id, name)
values(id, name)
commit transaction
end
This stored procedure is really just two statements, a select and a possible insert. I both statements inside of a transaction so that nothing can happen in between them to cause an exception. The id
column is a primary key, so I want to ensure that I don't insert the same id twice.
My question is: is this enough precaution to prevent problems? Do I need to put any hints in the select statement? If so, do I need HOLDLOCK, TABLOCKX
? This is new material for me.
EDIT: Suggested answer
create proc EmployeeInsertIfNotExists
(@id int, @name varchar(50))
as
begin
SET XACT_ABORT ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin transaction
if not exists(select * from tbl where id = @id)
insert into tbl(id, name)
values(id, name)
commit transaction
end