Var değilse, aynı anda yerleştirin


13

Saklı bir yordamda eklerim ile eşzamanlılık sorunları yaşıyorum. Prosedürün ilgili kısmı şudur:

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

Bu depolanan proc'ların 3 veya 4'ünü eşzamanlı olarak çalıştırdığımızda bazen birden fazla kesici uç alırız.

Ben böyle sabitleme planlıyorum:

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

Soru şu ki, sql sunucusunda kopya olmadan eşzamanlı olarak nasıl eklenir? Sadece bir kez eklemek için TOP kullanmak zorunda olduğum gerçeği beni rahatsız ediyor.


1
TOP kullanmak zorunda değilsiniz. FROM tablo başvurusunu SELECT deyiminden kaldırın.
ErikE


@GSerg Doğru olduğunu düşünüyorum.
Chris

Yanıtlar:


7

serializableİpucu ile bir birleştirme deyimi kullanabilirsiniz .

merge table1 with (serializable) as T 
using (select @_othervalue as othervalue) as S
on T.othervalue = S.othervalue
when not matched then
  insert (othervalue) values (othervalue);

Yaklaşımınızı iki veya daha fazla bağlantıdan test ettiniz mi?
AK

2
@AlexKuznetsov - SO ile ilgili başka bir soru için bir süre önce yaptım. SSMS'de iki sekme kullandım. İlk önce insert ... where not exist ...deseni test etti ve kilitlenme ve anahtar ihlalleri alabileceğinizi gördü, böylece updlock ve serileştirilebilir kullanmanız gerekiyordu. Daha sonra birleştirme deyimini test ettim ve işleri biraz daha iyi işleyeceğini düşündüm ve orada hiçbir kilitlenme olmadığı için yaptım, ancak hala önemli ihlaller olmamak için serileştirilebilir kullanmak zorunda kaldım.
Mikael Eriksson

1
Bu gerçekten harika bir cevap.
Chris Marisic

5

'Othervalue' sütununda kopyalar istemiyorsanız unique constraint, o sütunda bir oluşturarak bunu yapabilirsiniz . Sorgu şu şekildedir:

 ALTER TABLE table1
 ADD CONSTRAINT unique_c_othervalue UNIQUE(othervalue)

Bir sorgu 'othervalue' sütununa yinelenen bir değer eklemeye çalışırsa bu bir hatayı geri atar.


Benzersiz kısıtlama iki sıralı bir demetse bu nasıl çalışır?
Chris

1
@Chris Satırları kapsayan benzersiz bir kısıtlamanız nasıl var?
Aaron Bertrand

@Aaron Muhtemelen terminolojim kapalı, ama birlikte benzersiz olması gereken iki satır var. Bunun şemamızda uygulandığını sanmıyorum.
Chris

2

@StanleyJohns'ın önerdiği gibi benzersiz bir kısıtlama kullanın. Daha sonra ekleme ekstrenizin etrafında BEGIN TRY END TRY kullanın.

select @_id = Id from table1 where othervalue = @_othervalue
IF( @_id IS NULL)
BEGIN
    BEGIN TRY
        insert into table1 (othervalue) values (@_othervalue)
        select @_id = Id from table1 where othervalue = @_othervalue        
    END TRY
    BEGIN CATCH
        select @_id = Id from table1 where othervalue = @_othervalue        
    END CATCH
END
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.