Drupal 7 में डेटाबेस के साथ काम — पाठ 11 — मर्ज क्वेरीज़ (MERGE)
मर्ज क्वेरीज़ (Merge Queries) एक विशेष हाइब्रिड प्रकार की क्वेरी होती हैं। यद्यपि इन क्वेरीज़ का सिंटैक्स SQL 2003 मानक में परिभाषित किया गया था, वास्तव में बहुत कम डेटाबेस हैं जो इस सिंटैक्स का प्रत्यक्ष समर्थन करते हैं। हालांकि, अधिकांश डेटाबेस इस कार्यक्षमता को अलग-अलग तरीकों से लागू करते हैं, अपने स्वयं के सिंटैक्स के माध्यम से। Drupal में मर्ज क्वेरी कंस्ट्रक्टर इस पूरी अवधारणा को अमूर्त (abstract) रूप में प्रस्तुत करता है, ताकि यह हर डेटाबेस के लिए अलग-अलग तरीके से संकलित (compiled) हो सके।
सरल शब्दों में, एक मर्ज क्वेरी INSERT और UPDATE क्वेरी का संयोजन होती है। यदि कोई शर्त (condition) पूरी होती है — यानी कोई रिकॉर्ड पहले से मौजूद है — तो एक क्वेरी (UPDATE) चलती है। यदि शर्त पूरी नहीं होती — यानी रिकॉर्ड मौजूद नहीं है — तो दूसरी क्वेरी (INSERT) निष्पादित होती है। यह अक्सर निम्नलिखित PHP कोड के समान होती है:
<?php if (db_result(db_query("SELECT COUNT(*) FROM {example} WHERE id=:id", array(':id' => $id))->fetchField())) { // इस स्थिति में अपडेट चलाएँ (WHERE id = $id) } else { // अन्यथा नई पंक्ति डालें (INSERT), जहाँ id = $id होगा } ?>
वास्तविक कार्यान्वयन (implementation) डेटाबेस के प्रकार के आधार पर अलग-अलग होता है। ध्यान देने योग्य बात यह है कि यद्यपि मर्ज क्वेरीज़ की अवधारणा में यह एक atomic operation होती है, लेकिन यह वास्तव में परमाणु (atomic) होगी या नहीं, यह इस्तेमाल किए गए डेटाबेस पर निर्भर करता है। उदाहरण के लिए, MySQL में यह एक एटोमिक ऑपरेशन के रूप में लागू की जाती है, लेकिन ऊपर दिया गया PHP उदाहरण एटोमिक नहीं है।
सरल उदाहरण
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->execute(); ?>
इस उदाहरण में, हम "example" नामक टेबल के साथ काम कर रहे हैं। हम एक कुंजी फ़ील्ड ‘name’ निर्धारित करते हैं, जिसका मान $name है, और फिर field1 तथा field2 के लिए मान सेट करते हैं।
यदि टेबल में पहले से ऐसी पंक्ति मौजूद है जहाँ name = $name, तो field1 और field2 को नए मानों से अपडेट किया जाएगा। यदि ऐसी कोई पंक्ति नहीं है, तो एक नई पंक्ति बनाई जाएगी जिसमें name = $name और field1 = $value1, field2 = $value2 होंगे।
शर्तों के आधार पर अपडेट सेट करना
कभी-कभी आपको यह तय करना पड़ सकता है कि यदि रिकॉर्ड मौजूद है तो कुछ फ़ील्ड अपडेट हों, और यदि नहीं है तो अलग मान डाले जाएँ। ऐसा करने के दो तरीके हैं:
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->updateFields(array( 'field1' => $alternate1, )) ->execute(); ?>
ऊपर दिया गया उदाहरण पहले उदाहरण के समान कार्य करता है, केवल इतना अंतर है कि यदि रिकॉर्ड पहले से मौजूद है, तो केवल field1 का मान $alternate1 से अपडेट किया जाएगा। यदि रिकॉर्ड मौजूद नहीं है, तो नया रिकॉर्ड field1 = $value1 और field2 = $value2 के साथ बनाया जाएगा।
updateFields() मेथड केवल एक एसोसिएटिव ऐरे (या दो समानांतर इंडेक्स वाले ऐरे — एक फ़ील्ड्स के लिए और एक मानों के लिए) स्वीकार करता है। दोनों ऐरे का क्रम समान होना चाहिए।
Expression (अभिव्यक्ति) आधारित अपडेट
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->expression('field1', 'field1 + :inc', array(':inc' => 1)) ->execute(); ?>
इस उदाहरण में, यदि रिकॉर्ड पहले से मौजूद है, तो field1 का मान 1 से बढ़ा दिया जाएगा। यह तकनीक काउंटर (counter) जैसे फ़ील्ड्स के लिए बहुत उपयोगी होती है — जैसे किसी इवेंट के घटित होने पर मान को बढ़ाना।
यदि रिकॉर्ड मौजूद नहीं है, तो सामान्य रूप से एक नया रिकॉर्ड बनाया जाएगा जिसमें field1 = $value1 और field2 = $value2 होंगे।
expression() को कई बार कॉल किया जा सकता है — प्रत्येक फ़ील्ड के लिए एक बार। पहला पैरामीटर फ़ील्ड का नाम है, दूसरा SQL अभिव्यक्ति है जिसे लागू किया जाना है, और तीसरा पैरामीटर एक वैकल्पिक ऐरे है जिसमें प्लेसहोल्डर मान होते हैं।
यह आवश्यक नहीं है कि expression() में शामिल फ़ील्ड पहले fields() में भी परिभाषित किया गया हो।
सीमित अपडेट (Selective Update)
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->updateExcept('field1') ->execute(); ?>
updateExcept() मेथड या तो फ़ील्ड्स के एक ऐरे को स्वीकार करता है या कई फ़ील्ड्स को अलग-अलग पैरामीटर के रूप में। जो फ़ील्ड्स updateExcept() में निर्दिष्ट हैं, वे केवल नए रिकॉर्ड्स में सेट होंगी, लेकिन पहले से मौजूद रिकॉर्ड्स के अपडेट के दौरान उन्हें अनदेखा किया जाएगा।
उदाहरण के लिए, यदि कोई रिकॉर्ड पहले से मौजूद है (name = $name), तो केवल field2 का मान अपडेट होगा और field1 वैसा ही रहेगा। यदि रिकॉर्ड मौजूद नहीं है, तो field1 और field2 दोनों सेट होंगे।
प्राथमिकता नियम (Priority Rules)
उपरोक्त API आपको इतनी लचीलापन देता है कि आप कभी-कभी ऐसा अनुरोध बना सकते हैं जो तर्कसंगत न हो। उदाहरण के लिए, यदि आपने किसी फ़ील्ड को एक साथ ignore और expression() दोनों सेट कर दिया। इन संभावित त्रुटियों को कम करने के लिए कुछ नियम लागू किए जाते हैं:
- यदि किसी फ़ील्ड के लिए expression() परिभाषित है, तो उसे update() और updateExcept() दोनों से अधिक प्राथमिकता दी जाएगी।
- यदि कोई मान update() और updateExcept() दोनों में दिया गया है, तो update() को प्राथमिकता मिलेगी।
- यदि केवल update() में कुछ फ़ील्ड निर्दिष्ट हैं, तो केवल वही फ़ील्ड अपडेट होंगे — अन्य फ़ील्ड्स अनदेखी की जाएँगी।
ध्यान दें कि फिर भी ऐसा संभव है कि आप कुछ ऐसे मर्ज क्वेरी संयोजन बना लें जो तार्किक रूप से अर्थहीन हों। इसलिए हमेशा अपने कोड की तार्किकता की जाँच करें।