2008-08-01 9 views
69

MySQL में यह अविश्वसनीय रूप से उपयोगी अभी तक उचित REPLACE INTO एसक्यूएल कमांड है।MySQL प्रतिस्थापन के SQL सर्वर 2005 कार्यान्वयन INTO?

क्या यह आसानी से SQL सर्वर 2005 में अनुकरण किया जा सकता है? जब यह आवेदन में कर रहे हैं और इसलिए हमेशा बयान के 2 संस्करण रखने

एक नई लेन-देन शुरू, एक Select() कर और फिर या तो UPDATE या INSERT और COMMIT हमेशा एक दर्द का एक छोटा सा है, विशेष रूप से।

मुझे आश्चर्य है कि SQL Server 2005 में ऐसे फ़ंक्शन को लागू करने के लिए कोई आसान और सार्वभौमिक तरीका है?

उत्तर

53

यह ऐसा कुछ है जो मुझे MSSQL (rant on my blog) के बारे में परेशान करता है। मेरी इच्छा है कि एमएसएसएलएल समर्थित upsert

@ Dillie-ओ के कोड बड़े एसक्यूएल संस्करणों (+1 वोट) में एक अच्छा तरीका है, लेकिन यह अभी भी मूल रूप से दो आईओ परिचालन (exists और फिर update या insert)

एक से थोड़ा बेहतर तरीका नहीं है है this post, मूल रूप से पर:

--try an update 
update tablename 
set field1 = 'new value', 
    field2 = 'different value', 
    ... 
where idfield = 7 

--insert if failed 
if @@rowcount = 0 and @@error = 0 
    insert into tablename 
      (idfield, field1, field2, ...) 
    values (7, 'value one', 'another value', ...) 

यह अगर यह एक अद्यतन है, या दो एक डालने अगर एक आईओ संचालन करने के लिए इसे कम कर देता है।

एमएस Sql2008 एसक्यूएल से merge का परिचय: 2003 मानक:

merge tablename as target 
using (values ('new value', 'different value')) 
    as source (field1, field2) 
    on target.idfield = 7 
when matched then 
    update 
    set field1 = source.field1, 
     field2 = source.field2, 
     ... 
when not matched then 
    insert (idfield, field1, field2, ...) 
    values (7, source.field1, source.field2, ...) 

अब यह वास्तव में सिर्फ एक आईओ आपरेशन, लेकिन :-(

+0

ग्रेट, धन्यवाद! चयन को बचाता है और अक्सर परिस्थितियों में एक टेरनेक्शन की आवश्यकता नहीं होती है जहां मैं सुनिश्चित कर सकता हूं कि अद्यतन और "मेरे" सम्मिलन के बीच, उस कुंजी के लिए कोई अन्य सम्मिलन नहीं है। –

+1

@ माइकल यदि आप इस समाधान का उपयोग करने जा रहे हैं तो आप इस तालिका पर एक अद्वितीय अनुक्रमणिका और डुप्लिकेट कुंजी त्रुटियों के लिए हैंडलिंग करते हैं। –

+3

@ केथ आपके मर्ज स्टेटमेंट काम नहीं करता है। 'MERGE' 'WHERE' क्लॉज का समर्थन नहीं करता है, आपको' USING' और 'ON' का उपयोग करके फिर से लिखना होगा। साथ ही, जब तक आप 'साथ (होल्डॉक)' जोड़ते हैं, वहां एक दौड़ और समवर्ती 'INSERT की घटना हो सकती है, उनमें से एक कुंजी संघर्ष के कारण विफल हो रही है। –

19

जो कार्यक्षमता आप खोज रहे हैं उसे पारंपरिक रूप से यूपीएसईआरटी कहा जाता है। कम से कम यह जानकर कि आप क्या कह रहे हैं उसे ढूंढने में आपकी मदद कर सकते हैं।

मुझे नहीं लगता कि SQL Server 2005 के पास ऐसा करने का कोई शानदार तरीका है। 2008 में मेरिज स्टेटमेंट पेश किया गया है जिसका उपयोग इसे पूरा करने के लिए किया जा सकता है: http://www.databasejournal.com/features/mssql/article.php/3739131 या http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx

मर्ज 2005 के बीटा में उपलब्ध था, लेकिन उन्होंने इसे अंतिम रिलीज में हटा दिया।

15

क्या Upsert/मर्ज कर रहा है के प्रभाव के लिए कुछ है ...

IF EXISTS (SELECT * FROM [Table] WHERE Id = X) 
    UPDATE [Table] SET... 
ELSE 
    INSERT INTO [Table] 

तो उम्मीद है कि उन लेखों का संयोजन है और इस छद्म कोड बातें चलती प्राप्त कर सकते हैं।

9

भयंकर कोड मैंने लिखा है एक blog post about this issue

। नीचे की रेखा यह है कि यदि आप सस्ते अपडेट चाहते हैं ... और आप समवर्ती उपयोग के लिए सुरक्षित रहना चाहते हैं। कोशिश करें:

update t 
set hitCount = hitCount + 1 
where pk = @id 

if @@rowcount < 1 
begin 
    begin tran 
     update t with (serializable) 
     set hitCount = hitCount + 1 
     where pk = @id 
     if @@rowcount = 0 
     begin 
     insert t (pk, hitCount) 
     values (@id,1) 
     end 
    commit tran 
end 

इस तरह आपके पास अपडेट के लिए 1 ऑपरेशन और आवेषण के लिए अधिकतम 3 ऑपरेशन हैं। इसलिए, यदि आप आमतौर पर इसे अपडेट कर रहे हैं तो यह एक सुरक्षित सस्ता विकल्प है।

मैं भी सावधान रहूंगा जो समवर्ती उपयोग के लिए असुरक्षित कुछ भी नहीं है। उत्पादन में प्राथमिक कुंजी उल्लंघन या डुप्लिकेट पंक्तियां प्राप्त करना वास्तव में आसान है।