SQL सर्वर में INSERT INTO SELECT क्वेरी में डुप्लिकेट से बचें


109

मेरे पास निम्नलिखित दो तालिकाएँ हैं:

Table1
----------
ID   Name
1    A
2    B
3    C

Table2
----------
ID   Name
1    Z

मुझे इसमें से डेटा सम्मिलित Table1करना होगा Table2। मैं निम्नलिखित सिंटैक्स का उपयोग कर सकता हूं:

INSERT INTO Table2(Id, Name) SELECT Id, Name FROM Table1

हालाँकि, मेरे मामले में, डुप्लिकेट आईडी मौजूद हो सकती है Table2(मेरे मामले में, यह सिर्फ " 1") है और मैं इसे फिर से कॉपी नहीं करना चाहता क्योंकि यह एक त्रुटि है।

मैं कुछ इस तरह लिख सकता हूं:

IF NOT EXISTS(SELECT 1 FROM Table2 WHERE Id=1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1 
ELSE
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1 WHERE Table1.Id<>1

क्या बिना उपयोग के ऐसा करने का एक बेहतर तरीका है IF - ELSE? मैं INSERT INTO-SELECTकुछ शर्त के आधार पर दो बयानों से बचना चाहता हूं ।

जवाबों:


201

का उपयोग कर NOT EXISTS:

INSERT INTO TABLE_2
  (id, name)
SELECT t1.id,
       t1.name
  FROM TABLE_1 t1
 WHERE NOT EXISTS(SELECT id
                    FROM TABLE_2 t2
                   WHERE t2.id = t1.id)

का उपयोग कर NOT IN:

INSERT INTO TABLE_2
  (id, name)
SELECT t1.id,
       t1.name
  FROM TABLE_1 t1
 WHERE t1.id NOT IN (SELECT id
                       FROM TABLE_2)

का उपयोग कर LEFT JOIN/IS NULL:

INSERT INTO TABLE_2
  (id, name)
   SELECT t1.id,
          t1.name
     FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.id = t1.id
    WHERE t2.id IS NULL

तीन विकल्पों में से, LEFT JOIN/IS NULLकम कुशल है। देखें अधिक जानकारी के लिए इस लिंक पर


9
NOT EXISTS संस्करण पर एक स्पष्टीकरण, आपको एक (HOLDLOCK) संकेत के साथ की आवश्यकता होगी या कोई लॉक नहीं लिया जाएगा (क्योंकि लॉक करने के लिए कोई पंक्तियाँ नहीं हैं!) इसलिए एक और धागा आपके नीचे पंक्ति सम्मिलित कर सकता है।
आईडीसोर्पोटी

3
दिलचस्प है, क्योंकि मैंने हमेशा माना है कि उप-चयन से तेज जुड़ना। शायद यह केवल सीधे जुड़ने के लिए है, और बाएं जोड़ पर लागू नहीं है।
डंकन

1
डंकन, ज्वाइनिंग अक्सर तेज होती है जब वे सहसंबन्धित उपश्रेणी होते हैं। यदि आपके पास चयन सूची में उपश्रेणी है तो एक जुड़ाव अक्सर तेज होगा।
HLGEM

9
NOT EXISTSसमग्र प्राथमिक कुंजी के साथ विशेष रूप से उपयोगी है, NOT INतब काम नहीं करेगा
tomash

1
@OMGPies - अधिक विवरण के लिए आपका लिंक मृत प्रतीत होता है। क्या आपके पास एक और है जो उपयोगी हो सकता है?
फ्रीमैन

36

MySQL में आप ऐसा कर सकते हैं:

INSERT IGNORE INTO Table2(Id, Name) SELECT Id, Name FROM Table1

SQL सर्वर के समान कुछ भी है?


5
इस पर मुझे शिक्षित करने के लिए +1। बहुत अच्छा वाक्यविन्यास। निश्चित रूप से छोटा और मेरे द्वारा उपयोग किए जाने वाले से बेहतर। दुर्भाग्य से Sql सर्वर में यह नहीं है।
आशीष गुप्ता

13
पूरी तरह से सच नहीं है। जब आप एक अद्वितीय सूचकांक बनाते हैं, तो आप इसे "डुप्लिकेट को अनदेखा करने" के लिए सेट कर सकते हैं, जिस स्थिति में एसक्यूएल सर्वर डुप्लिकेट को जोड़ने के किसी भी प्रयास को अनदेखा करेगा।
IAMIC

2
और SQL सर्वर अभी भी नहीं कर सकता ... दयनीय।
स्मैक जैक 4

1
तो SQL सर्वर अभी भी खिचड़ी भाषा?
ingus

8

मुझे सिर्फ एक समान समस्या थी, DISTINCT कीवर्ड जादू काम करता है:

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1

21
जब तक मैं आपको पूरी तरह से गलत नहीं समझ लेता, यह तब तक काम करेगा जब आपके द्वारा डाले जा रहे सेट में डुप्लिकेट हो । हालाँकि, यह निर्धारित करने में मदद नहीं करेगा कि आप जो सेट लगा रहे हैं, वह insert intoतालिका में पहले से मौजूद डेटा का डुप्लिकेट हो सकता है ।
फ्रीमैन

5

मैं हाल ही में एक ही समस्या का सामना कर रहा था ...
Heres ने एमएस SQL ​​सर्वर 2017 में मेरे लिए क्या काम किया ...
प्राथमिक कुंजी को तालिका 2 में आईडी पर सेट किया जाना चाहिए ...
स्तंभ और स्तंभ गुण दोनों के बीच एक ही होना चाहिए टेबल। यह पहली बार काम करेगा जब आप नीचे की स्क्रिप्ट चलाएंगे। तालिका 1 में डुप्लिकेट आईडी, सम्मिलित नहीं होगा ...

अगर आप इसे दूसरी बार चलाते हैं, तो आपको ए

प्राथमिक कुंजी की त्रुटि का उल्लंघन

यह कोड है:

Insert into Table_2
Select distinct *
from Table_1
where table_1.ID >1

4

आईएएनसी द्वारा सुझाए गएignore Duplicates अद्वितीय सूचकांक का उपयोग करना यहां एक समान मुद्दे के लिए मेरा समाधान था, विकल्प के साथ सूचकांक का निर्माण करनाWITH IGNORE_DUP_KEY

In backward compatible syntax
, WITH IGNORE_DUP_KEY is equivalent to WITH IGNORE_DUP_KEY = ON.

रेफरी: index_option


4

SQL सर्वर से आप तालिका के लिए एक अद्वितीय कुंजी इंडेक्स सेट कर सकते हैं (कॉलम जिसमें अद्वितीय होने की आवश्यकता है)

Sql सर्वर से टेबल डिज़ाइन सेलेक्ट इंडेक्स / कीज़ पर राइट क्लिक करें

कॉलम (एस) चुनें जो डुप्लिकेट नहीं होगा, फिर विशिष्ट कुंजी टाइप करें


1

थोड़ा बंद विषय, लेकिन यदि आप डेटा को एक नई तालिका में माइग्रेट करना चाहते हैं, और संभव डुप्लिकेट मूल तालिका में हैं , और संभवतः डुप्लिकेट किए गए कॉलम एक आईडी नहीं है, एक GROUP BYहोगा:

INSERT INTO TABLE_2
(name)
  SELECT t1.name
  FROM TABLE_1 t1
  GROUP BY t1.name

-1

प्रत्यय DELETEसे पहले एक सरल INSERT:

DELETE FROM Table2 WHERE Id = (SELECT Id FROM Table1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1

स्विचिंग Table1के लिए Table2जो तालिका के आधार पर Idऔर nameअपने आप युग्मन आप संरक्षित करना चाहते।


3
कृपया ऐसा न करें। आप मूल रूप से कह रहे हैं "मेरे पास जो भी डेटा है वह बेकार है, चलो बस यह नया डेटा डालें!"
अंधिर

@ और अगर किसी कारण से "टेबल 2" को "इंसर्ट" के बाद गिराया नहीं जाना चाहिए, तो अन्य तरीकों का उपयोग करें, लेकिन ओपी ने जो पूछा वह हासिल करने के लिए यह पूरी तरह से वैध तरीका है।
साकारो

1
मान्य, लेकिन निश्चित रूप से धीमी और संभावित लेनदेन के बिना भ्रष्ट। यदि आप इस मार्ग पर जाते हैं, तो लेन-देन में लपेटें।
MC9000
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.