सम्मिलित न होने पर समवर्ती रूप से सम्मिलित करें


13

मैं एक संग्रहीत कार्यविधि में अपने आवेषण के साथ समसामयिक समस्याएँ कर रहा हूँ। प्रक्रिया का प्रासंगिक हिस्सा यह है:

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

जब हम इनमें से 3 या 4 को संगृहीत खरीद के समवर्ती रूप से चलाते हैं, तो हमें इस अवसर पर कई आवेषण मिलते हैं।

मैं इसे ठीक करने की योजना बना रहा हूं:

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

सवाल यह है कि, sql सर्वर में डुप्लिकेट के बिना समवर्ती कैसे सम्मिलित किया जाए? तथ्य यह है कि मुझे केवल एक बार सम्मिलित करने के लिए TOP का उपयोग करना है जो मुझे परेशान करता है।


1
आपको TOP का उपयोग नहीं करना है। चयन कथन से FROM तालिका संदर्भ निकालें।
EricE


@GSerg मुझे लगता है कि आप सही हैं।
क्रिस

जवाबों:


7

आप serializableसंकेत के साथ मर्ज कथन का उपयोग कर सकते हैं ।

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);

क्या आपने दो या अधिक कनेक्शनों से अपने दृष्टिकोण का परीक्षण किया?
AK

2
@AlexKuznetsov - मैंने इसे कुछ समय पहले SO पर एक और प्रश्न के लिए किया था। मैंने SSMS में दो टैब का उपयोग किया। पहले insert ... where not exist ...पैटर्न का परीक्षण किया और पाया कि आप गतिरोध और प्रमुख उल्लंघन प्राप्त कर सकते हैं इसलिए अपडेटलॉक और क्रमिक का उपयोग करना आवश्यक था। फिर मैंने मर्ज स्टेटमेंट का परीक्षण किया और सोचा कि यह चीजों को थोड़ा बेहतर ढंग से हैंडल करेगा और ऐसा इसलिए हुआ क्योंकि जहां कोई गतिरोध नहीं था, लेकिन मुझे अभी भी महत्वपूर्ण उल्लंघन नहीं करने के लिए सीरियल करने योग्य उपयोग करना था।
मिकेल एरिकसन

1
यह एक बहुत बढ़िया जवाब है।
क्रिस मैरिसिक

5

यदि आप oth othervalue ’कॉलम पर डुप्लिकेट नहीं चाहते हैं, तो आप unique constraintउस कॉलम पर बनाकर ऐसा कर सकते हैं । प्रश्न यह होगा:

 ALTER TABLE table1
 ADD CONSTRAINT unique_c_othervalue UNIQUE(othervalue)

यदि कोई क्वेरी 'othervalue' कॉलम में डुप्लिकेट मान सम्मिलित करने का प्रयास करती है, तो यह एक त्रुटि वापस लाएगा।


यदि अद्वितीय बाधा एक दो पंक्ति टपल है तो यह कैसे काम करेगा?
क्रिस

1
@ क्रिस कैसे आप एक अद्वितीय बाधा है कि पंक्तियों में फैला है?
हारून बर्ट्रेंड

@ ऐरॉन मैं शायद अपनी शब्दावली बंद कर रहा हूं, लेकिन हमारे पास दो पंक्तियां हैं जो एक साथ अद्वितीय होनी चाहिए। मुझे नहीं लगता कि यह हमारे स्कीमा में लागू है।
क्रिस

2

@StanleyJohns की सिफारिश की तरह एक अद्वितीय बाधा का उपयोग करें। फिर अपने सम्मिलित विवरण के चारों ओर BEGIN TRY END TRY का उपयोग करें।

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.