TATECHATLAS
◎ हिन्दी
डेटा और डेटाबेस

PostgreSQL INSERT ON CONFLICT: यूनिक लक्ष्यों के साथ सही अपसर्ट, DO NOTHING बनाम DO UPDATE

यूनिक प्रतिबंधों के आधार पर पंक्तियों को परमाणु रूप से डालने या अपडेट करने के लिए ON CONFLICT का उपयोग करें। सटीक संघर्ष लक्ष्य निर्दिष्ट करें, डुप्लिकेट इनपुट पंक्तियों को संभालें, और समझें कि बहिष्कृत मान संचय नहीं बल्कि प्रतिस्थापित करते हैं।

इस पृष्ठ पर

PostgreSQL में INSERT ... ON CONFLICT स्टेटमेंट एक परमाणु अपसर्ट तंत्र प्रदान करता है। यह पंक्तियों को डालने का प्रयास करता है; यदि कोई पंक्ति निर्दिष्ट यूनिक प्रतिबंध या इंडेक्स (संघर्ष लक्ष्य) का उल्लंघन करती है, तो यह या तो कुछ नहीं करता है (DO NOTHING) या मौजूदा पंक्ति को अपडेट करता है (DO UPDATE)। संघर्ष लक्ष्य को यूनिक नियम को सही ढंग से पहचानना चाहिए। EXCLUDED स्यूडो-टेबल अपडेट के लिए प्रस्तावित डालने के मानों तक पहुंच प्रदान करता है। जबकि स्टेटमेंट प्रत्येक पंक्ति के लिए परमाणु है, यह व्यावसायिक स्तर की शब्दार्थ जैसे योगात्मक अपडेट या समवर्ती लेनदेन में एक बार ही प्रसंस्करण की गारंटी नहीं देता है।

वास्तविक यूनिकता नियम की पहचान करें

एक ON CONFLICT क्लॉज आर्बिटर प्रतिबंधों या इंडेक्स के उल्लंघन का समाधान करता है। ये यूनिक प्रतिबंध (प्राइमरी की, यूनिक) या यूनिक इंडेक्स हैं। दस्तावेज़ीकरण में कहा गया है कि ON CONFLICT DO UPDATE के लिए, एक संघर्ष लक्ष्य प्रदान करना आवश्यक है। यह लक्ष्य आर्बिटर इंडेक्स चुनकर वैकल्पिक क्रिया को ट्रिगर करने वाले संघर्षों को निर्दिष्ट करता है। नियम डेटाबेस स्तर पर लागू होता है, न कि एप्लिकेशन लॉजिक द्वारा। उदाहरण के लिए, एक तालिका inventory(sku text PRIMARY KEY, qty integer NOT NULL) में sku पर प्राइमरी की प्रतिबंध है। यह प्रतिबंध आर्बिटर है; डुप्लिकेट sku मान का कोई भी डालना एक संघर्ष है।

संघर्ष लक्ष्य चुनें

संघर्ष लक्ष्य यूनिक इंडेक्स अनुमान, कॉलम/एक्सप्रेशन का नाम, या ON CONFLICT ON CONSTRAINT के सीधे प्रतिबंध का नाम उपयोग कर सकता है। अनुमान अक्सर बेहतर होता है। inventory तालिका के लिए, sku पर प्राइमरी की ON CONFLICT (sku) द्वारा अनुमानित है। दस्तावेज़ीकरण में नोट किया गया है कि अनुमान उन सभी यूनिक इंडेक्स को चुनता है जिनमें बिल्कुल निर्दिष्ट कॉलम/एक्सप्रेशन होते हैं। यदि आप किसी प्रतिबंध का सीधे नाम देते हैं, तो वह उस प्रतिबंध से जुड़े इंडेक्स का उपयोग करता है। आंशिक यूनिक इंडेक्स के लिए, आपको संघर्ष लक्ष्य में WHERE क्लॉज शामिल करना चाहिए ताकि इंडेक्स प्रेडिकेट से मेल खा सके।

DO NOTHING का जानबूझकर उपयोग करें

ON CONFLICT DO NOTHING उन पंक्तियों को चुपचाप हटा देता है जो किसी आर्बिटर प्रतिबंध या इंडेक्स के साथ संघर्ष का कारण बनती हैं। संघर्ष लक्ष्य वैकल्पिक है; यदि इसे छोड़ दिया जाता है, तो सभी उपयोगी यूनिक प्रतिबंधों के साथ संघर्षों को संभाला जाता है। इसका उपयोग तब करें जब आप केवल नई पंक्तियां डालना चाहते हैं और डुप्लिकेट को अनदेखा करना चाहते हैं। उदाहरण के लिए, INSERT INTO inventory (sku, qty) VALUES ('A', 3) ON CONFLICT DO NOTHING; यदि SKU 'A' पहले से मौजूद है तो कुछ नहीं करता है। स्टेटमेंट सफल होता है, और लौटाया गया गणना वास्तव में डाली गई पंक्तियों की संख्या को इंगित करता है (इस मामले में शून्य)।

बहिष्कृत मानों से अपडेट करें

ON CONFLICT DO UPDATE मौजूदा संघर्ष वाली पंक्ति को संशोधित करता है। SET क्लॉज के भीतर, विशेष EXCLUDED उपनाम डालने के लिए मूल रूप से प्रस्तावित मानों तक पहुंच प्रदान करता है। दस्तावेज़ीकरण में निर्दिष्ट है कि किसी कॉलम को संदर्भित करते समय, तालिका का नाम शामिल न करें। inventory उदाहरण के लिए, INSERT INTO inventory (sku, qty) VALUES ('A', 3) ON CONFLICT (sku) DO UPDATE SET qty = EXCLUDED.qty; मौजूदा मात्रा को 3 से बदल देता है। यह मानों को जोड़ता नहीं है। योगात्मक अपडेट करने के लिए, आपको मौजूदा पंक्ति को स्पष्ट रूप से संदर्भित करना होगा: SET qty = inventory.qty + EXCLUDED.qty।

दो पंक्तियों का उदाहरण ट्रेस करें

मान लें कि दो पंक्तियाँ डालनी हैं जहाँ एक विवादित है और दूसरा नहीं। इन्वेंट्री में शुरू में ('A', 2) मौजूद है, तो निम्न कमांड चलाएँ: INSERT INTO inventory (sku, qty) VALUES ('A', 3), ('B', 5) ON CONFLICT (sku) DO UPDATE SET qty = EXCLUDED.qty;. SKU 'A' की पंक्ति विवादित है, जिससे इसकी qty को 3 पर सेट करने के लिए अपडेट ट्रिगर होता है। SKU 'B' की पंक्ति विवादित नहीं है और डाली जाती है। कमांड INSERT 0 2 लौटाता है, जो दर्शाता है कि दो पंक्तियाँ संसाधित हुईं (एक अपडेट की गई, एक डाली गई)। अंतिम स्थिति ('A', 3), ('B', 5) है।

एक स्टेटमेंट में डुप्लिकेट पंक्तियों को संभालें

PostgreSQL ON CONFLICT DO UPDATE को निर्धारणात्मक के रूप में दस्तावेज़ करता है: एक कमांड एक ही मौजूदा पंक्ति को एक से अधिक बार प्रभावित नहीं कर सकता। बार-बार प्रस्तावित कुंजियों के साथ, जैसे VALUES ('A', 3), ('A', 4), एक कार्डिनैलिटी उल्लंघन हो सकता है। इसे सटीक रूप से सामान्य डुप्लिकेट-कुंजी त्रुटि के रूप में वर्णित नहीं किया जा सकता जो ON CONFLICT के कार्य करने का मौका मिलने से पहले होती है। पहले या अंतिम प्रस्तावित मान के जीतने पर निर्भर न करें।

स्टेटमेंट सबमिट करने से पहले इनपुट को डुप्लिकेट हटाएं या स्पष्ट व्यावसायिक नियम के अनुसार बार-बार की गई कुंजियों को एकत्र करें। प्रतिस्थापन मात्राओं के लिए, निर्णय लें कि कौन सा अवलोकन जीतना चाहिए; योगात्मक मात्राओं के लिए, निर्णय लें कि योग करना उपयुक्त है या नहीं। स्टेटमेंट त्रुटि पर, इसके परिवर्तन आंशिक रूप से सफल अपसर्ट नहीं बनते हैं। एक स्पष्ट लेनदेन में, एप्लिकेशन की रोलबैक या सेवपॉइंट नीति का उपयोग करके पुनर्प्राप्त करें।

समवर्ती व्यवहार को समझें

ON CONFLICT DO UPDATE प्रत्येक पंक्ति के लिए परमाणु INSERT या UPDATE परिणाम की गारंटी देता है, यहां तक कि उच्च समवर्तिता के तहत भी। हालांकि, दस्तावेज़ चेतावनी देता है कि जब CREATE INDEX CONCURRENTLY या REINDEX CONCURRENTLY किसी यूनिक इंडेक्स पर चल रहा हो, तो उसी तालिका पर INSERT ... ON CONFLICT अप्रत्याशित रूप से यूनिक उल्लंघन के साथ विफल हो सकता है। स्टेटमेंट विवादित पंक्ति पर लॉक लेता है। यदि दो समवर्ती लेनदेन एक ही कुंजी डालने का प्रयास करते हैं, तो एक डालने के साथ सफल होगा, और दूसरा विवादित होगा और अब मौजूदा पंक्ति पर DO UPDATE क्रिया लेगा।

स्टेटमेंट से परे सीमाओं की जाँच करें

परमाणु अपसर्ट व्यावसायिक स्तर पर एक बार ही प्रसंस्करण की गारंटी नहीं देता है। योगात्मक अपडेट को पुनः प्रयास करने से मात्रा फिर से बढ़ सकती है जब तक कि एप्लिकेशन तार्किक ऑपरेशन को डुप्लिकेट नहीं हटाता। अन्य बाधाएं, अनुमतियां और ट्रिगर अभी भी स्टेटमेंट को अस्वीकार कर सकते हैं। डिफ़ॉल्ट रूप से, नल करने योग्य यूनिक कॉलम नल को अलग मानते हैं, कई नल की अनुमति देते हैं जब तक कि NULLS NOT DISTINCT निर्दिष्ट नहीं किया जाता। आंशिक यूनिक इंडेक्स केवल उनके प्रेडिकेट पर लागू होते हैं; विवाद-लक्ष्य अनुमान को एक उपयुक्त मध्यस्थ का चयन करना चाहिए।

क्या जाँचें

  • ON CONFLICT DO UPDATE के लिए, आपको एक संघर्ष लक्ष्य निर्दिष्ट करना होगा।
  • EXCLUDED उपनाम DO UPDATE SET क्लॉज में उपयोग के लिए प्रस्तावित डालने के मान प्रदान करता है।
  • DO UPDATE से पहले आर्बिटर कुंजी द्वारा प्रस्तावित पंक्तियों को डुप्लिकेट हटाएं: एक कमांड को एक ही मौजूदा पंक्ति को एक से अधिक बार प्रभावित नहीं करना चाहिए; दोहराई गई कुंजियां कार्डिनैलिटी उल्लंघन का कारण बन सकती हैं।
  • ON CONFLICT DO UPDATE प्रति पंक्ति परमाणु है लेकिन स्वचालित रूप से मात्रा नहीं जोड़ता है; आपको qty = inventory.qty + EXCLUDED.qty जैसा एक्सप्रेशन लिखना होगा।
  • आंशिक यूनिक आर्बिटर इंडेक्स के लिए, संघर्ष लक्ष्य में एक उपयुक्त इंडेक्स प्रेडिकेट शामिल करें ताकि PostgreSQL इच्छित इंडेक्स का अनुमान लगा सके।
  • कमांड टैग INSERT 0 N इंगित करता है कि N पंक्तियां डाली या अपडेट की गईं; oid हमेशा 0 होता है।
  • बिना संघर्ष लक्ष्य के ON CONFLICT DO NOTHING के लिए, किसी भी यूनिक प्रतिबंध के साथ संघर्षों को अनदेखा किया जाता है।
  • ON CONFLICT ON CONSTRAINT के सीधे प्रतिबंध का नाम देना उस प्रतिबंध से जुड़े इंडेक्स का उपयोग करता है।
  • परमाणु डालना-या-अपडेट व्यवहार सफलता की गारंटी नहीं देता है: असंबंधित प्रतिबंध, अनुमतियां, ट्रिगर या समवर्ती यूनिक-इंडेक्स रखरखाव अभी भी त्रुटियों का कारण बन सकता है।
  • यूनिक प्रतिबंध डिफ़ॉल्ट रूप से NULL को अलग मानते हैं, कई NULL पंक्तियों की अनुमति देते हैं जब तक कि NULLS NOT DISTINCT निर्दिष्ट न हो।

यह गाइड PostgreSQL INSERT ... ON CONFLICT का वर्णन करती है, न कि हर डेटाबेस के लिए सार्वभौमिक सिंटैक्स का। पंक्ति-स्तरीय परमाणुता एक बार ही बाहरी प्रभाव प्रदान नहीं करती है या व्यावसायिक मात्राओं को मान्य नहीं करती है। DO UPDATE से पहले परिभाषित व्यावसायिक नियम के अनुसार प्रस्तावित कुंजियों को डुप्लिकेट हटाएं। समवर्ती यूनिक-इंडेक्स रखरखाव और अन्य डेटाबेस जांचें अभी भी त्रुटियां उत्पन्न कर सकती हैं। छोटा inventory उदाहरण स्पष्टीकरणात्मक है, न कि निष्पादित परीक्षण है।

स्रोत

  1. PostgreSQL: INSERT and ON CONFLICT ↗
  2. PostgreSQL: unique constraints ↗
ऊपर जाएँ ↑