Tengo problemas de concurrencia con mis inserciones en un procedimiento almacenado. La parte relevante del procedimiento es esta:
select @_id = Id from table1 where othervalue = @_othervalue
IF( @_id IS NULL)
BEGIN
insert into table1 (othervalue) values (@_othervalue)
select @_id = Id from table1 where othervalue = @_othervalue
END
Cuando ejecutamos 3 o 4 de estos procesos almacenados simultáneamente, obtenemos múltiples inserciones en ocasiones.
Estoy planeando arreglar esto así:
insert into table1 (othervalue)
select TOP(1) @_othervalue as othervalue from table1 WITH(UPDLOCK)
where NOT EXISTS ( select * from table1 where othervalue = @_othervalue )
select @_id = Id from table1 where othervalue = @_othervalue
La pregunta es, ¿cómo insertar simultáneamente sin duplicados en el servidor SQL? El hecho de que tenga que usar TOP para insertar solo una vez me molesta.
Respuestas:
Podría usar una declaración de fusión con una
serializable
pista.fuente
insert ... where not exist ...
patrón y descubrió que puede obtener puntos muertos y violaciones de claves, por lo que allí era necesario usar updlock y serializable. Luego probé la declaración de fusión y pensé que manejaría las cosas un poco mejor, y lo hizo porque no había puntos muertos, pero todavía tenía que usar serializable para no tener violaciones clave.Si no desea duplicados en la columna 'otro valor', puede hacerlo creando un
unique constraint
en esa columna. La consulta sería:Esto arrojaría un error si una consulta intentara insertar un valor duplicado en la columna 'otro valor'.
fuente
Use una restricción única como la que recomienda @StanleyJohns. Luego, use BEGIN TRY END TRY alrededor de su declaración de inserción.
fuente