मर्ज क्वेरीज़ (Merge Queries)
मर्ज क्वेरीज़ (Merge Queries) एक विशेष प्रकार की हाइब्रिड क्वेरी होती हैं। यद्यपि इनके लिए सिंटैक्स SQL 2003 स्पेसिफिकेशन में परिभाषित किया गया है, लेकिन लगभग कोई भी डेटाबेस मानक सिंटैक्स को सपोर्ट नहीं करता। हालाँकि, उनमें से अधिकांश एक वैकल्पिक इम्प्लीमेंटेशन प्रदान करते हैं जो डेटाबेस-विशिष्ट सिंटैक्स का उपयोग करता है। Drupal में मर्ज क्वेरी बिल्डर मर्ज क्वेरी की अवधारणा को एक स्ट्रक्चर्ड ऑब्जेक्ट में एब्स्ट्रैक्ट करता है, जिसे प्रत्येक डेटाबेस के लिए उपयुक्त सिंटैक्स में कम्पाइल किया जा सकता है। इन्हें कभी-कभी "UPSERT" क्वेरीज़ भी कहा जाता है, जो UPDATE और INSERT का संयोजन है।
सामान्य अर्थ में, मर्ज क्वेरी एक INSERT क्वेरी और UPDATE क्वेरी का संयोजन है। यदि कोई दी गई शर्त पूरी होती है, जैसे कि किसी दिए गए प्राइमरी की के साथ कोई पंक्ति पहले से मौजूद है, तो UPDATE क्वेरी चलाई जाती है। यदि नहीं, तो INSERT क्वेरी चलाई जाती है। सबसे सामान्य मामले में, यह इसके बराबर होता है:
if ($connection->query("SELECT COUNT(*) FROM {example} WHERE id = :id", [':id' => $id])->fetchField()) {
// Run an update using WHERE id = $id
}
else {
// Run an insert, inserting $id for id
}
वास्तविक इम्प्लीमेंटेशन डेटाबेस से डेटाबेस तक काफी अलग होता है। ध्यान दें कि यद्यपि मर्ज क्वेरीज़ अवधारणात्मक रूप से एटोमिक ऑपरेशन होती हैं, वे वास्तव में एटोमिक हो भी सकती हैं और नहीं भी, यह विशेष डेटाबेस की इम्प्लीमेंटेशन पर निर्भर करता है। उदाहरण के लिए, MySQL का इम्प्लीमेंटेशन एक अलग एटोमिक क्वेरी है, लेकिन ऊपर दिया गया साधारण केस नहीं है।
मर्ज क्वेरीज़ के लिए सबसे सामान्य रूप से प्रयुक्त इडियम नीचे दिए गए हैं।
सिर्फ इसे सेट करें
$connection->merge('example')
->key('name', $name)
->fields([
'field1' => $value1,
'field2' => $value2,
])
->execute();
ऊपर दिए गए उदाहरण में हम क्वेरी को "example" टेबल पर काम करने के लिए कहते हैं। फिर हम एक की फील्ड 'name' को $name मान के साथ निर्दिष्ट करते हैं। इसके बाद हम एक वैल्यूज़ की ऐरे सेट करने के लिए देते हैं।
यदि पहले से ऐसी कोई पंक्ति मौजूद है जहाँ "name" फील्ड का मान $name है, तो उस पंक्ति में field1 और field2 को नए दिए गए मानों से अपडेट किया जाएगा। यदि ऐसी कोई पंक्ति मौजूद नहीं है, तो एक नई पंक्ति बनाई जाएगी जिसमें name का मान $name, field1 का मान $value1 और field2 का मान $value2 होगा। इस प्रकार, क्वेरी के अंत में अंतिम परिणाम समान रहेगा, चाहे पंक्ति पहले से मौजूद हो या नहीं।
शर्तीय सेट (Conditional Set)
कुछ मामलों में यह आवश्यक हो सकता है कि की() फील्ड्स द्वारा परिभाषित रिकॉर्ड पहले से मौजूद है या नहीं, इसके आधार पर अलग-अलग मान सेट किए जाएँ। ऐसा करने के दो तरीके हैं।
$connection->merge('example')
->insertFields([
'field1' => $value1,
'field2' => $value2,
])
->updateFields([
'field1' => $alternate1,
])
->key('name', $name)
->execute();
ऊपर दिया गया उदाहरण पहले वाले जैसा ही व्यवहार करेगा, सिवाय इसके कि यदि रिकॉर्ड पहले से मौजूद है और हम उसे अपडेट कर रहे हैं, तो field1 का मान $alternate1 होगा बजाय $value1 के, और field2 प्रभावित नहीं होगा। updateFields() मेथड या तो एक एसोसिएटिव ऐरे लेता है या फिर दो समानांतर न्यूमेरिक ऐरे: एक फील्ड्स का और दूसरा वैल्यूज़ का, जिन्हें उसी क्रम में होना चाहिए।
$connection->merge('example')
->key('name', $name)
->fields([
'field1' => $value1,
'field2' => $value2,
])
->expression('field1', 'field1 + :inc', [':inc' => 1])
->execute();
इस उदाहरण में, यदि रिकॉर्ड पहले से मौजूद है, तो field1 को उसके वर्तमान मान + 1 से अपडेट किया जाएगा। यह "काउंटर क्वेरीज़" के लिए बहुत उपयोगी है, जहाँ आप हर बार किसी विशेष इवेंट के होने पर डेटाबेस में एक काउंटर को इन्क्रीमेंट करना चाहते हैं। field2 का मान फिर भी समान रहेगा, चाहे रिकॉर्ड मौजूद हो या नहीं।
ध्यान दें कि expression() कई बार कॉल किया जा सकता है, प्रत्येक फील्ड के लिए जिसे एक्सप्रेशन से सेट करना है यदि रिकॉर्ड पहले से मौजूद है। पहला पैरामीटर फील्ड है, दूसरा SQL एक्सप्रेशन का हिस्सा है जो दर्शाता है कि फील्ड को किस एक्सप्रेशन पर सेट करना है, और वैकल्पिक तीसरा पैरामीटर प्लेसहोल्डर वैल्यूज़ का ऐरे है जिन्हें एक्सप्रेशन में डाला जाएगा।
यह भी आवश्यक नहीं है कि expression() में उपयोग किया गया फील्ड पहले से fields() में हो।
ऊपर दिए गए API को देखते हुए, यह पूरी तरह संभव है कि ऐसी क्वेरीज़ परिभाषित की जाएँ जिनका कोई तार्किक अर्थ नहीं है, जैसे कि यदि किसी फील्ड को दोनों ही "इग्नोर" और "एक्सप्रेशन से सेट" के लिए निर्दिष्ट कर दिया जाए। संभावित त्रुटियों को कम करने के लिए, निम्नलिखित नियम लागू होते हैं:
- यदि किसी फील्ड के लिए
expression()सेट किया गया है, तो यहupdateFields()पर प्राथमिकता रखेगा। - यदि मान
updateFields()में निर्दिष्ट किए गए हैं, तो केवल वही फील्ड्स बदले जाएँगे यदि रिकॉर्ड पहले से मौजूद है। जो फील्ड्सupdateFields()में निर्दिष्ट नहीं किए गए हैं, वे अप्रभावित रहेंगे।
ध्यान दें कि फिर भी ऐसी क्वेरीज़ परिभाषित करना संभव है जिनका कोई अर्थ नहीं है। डेवलपर की जिम्मेदारी है यह सुनिश्चित करना कि कोई बेमतलब की क्वेरी न लिखी जाए, क्योंकि ऐसे मामलों में व्यवहार परिभाषित नहीं है।