इन्सर्ट क्वेरीज़ (Insert Queries)
इन्सर्ट क्वेरीज़ हमेशा क्वेरी बिल्डर ऑब्जेक्ट का उपयोग करके लिखी जानी चाहिए। कुछ डेटाबेस में LOB (Large OBject, जैसे MySQL में TEXT) और BLOB (Binary Large OBject) फ़ील्ड्स की विशेष हैंडलिंग की आवश्यकता होती है, इसलिए एक एब्स्ट्रैक्शन लेयर की ज़रूरत होती है ताकि अलग-अलग डेटाबेस ड्राइवर्स अपनी आवश्यक विशेष हैंडलिंग लागू कर सकें।
इन्सर्ट क्वेरीज़ insert() मेथड का उपयोग करके इस प्रकार चलाई जाती हैं:
$query = $connection->insert('mytable', $options);
यह एक इन्सर्ट क्वेरी ऑब्जेक्ट बनाता है, जो mytable टेबल में एक या अधिक रिकॉर्ड्स डालता है। ध्यान दें कि टेबल के नाम के लिए आकृति ब्रेसेस (curly braces) की आवश्यकता नहीं होती, क्योंकि क्वेरी बिल्डर इसे स्वचालित रूप से हैंडल कर लेता है।
इन्सर्ट क्वेरी ऑब्जेक्ट फ्लुएंट API का उपयोग करता है। यानी, सभी मेथड्स (सिवाय execute() के) उसी ऑब्जेक्ट को लौटाते हैं, जिससे मेथड कॉल्स को चेन करना संभव होता है। कई मामलों में इसका मतलब यह है कि क्वेरी ऑब्जेक्ट को किसी वेरिएबल में सेव करने की ज़रूरत नहीं होती।
इन्सर्ट क्वेरी ऑब्जेक्ट विभिन्न ज़रूरतों को पूरा करने के लिए कई पैटर्न्स सपोर्ट करता है। सामान्यतः वर्कफ़्लो में उन फ़ील्ड्स को निर्दिष्ट करना शामिल होता है जिनमें वैल्यू डाली जाएगी, उन वैल्यूज़ को परिभाषित करना और फिर क्वेरी चलाना। नीचे सबसे सामान्य और अनुशंसित पैटर्न्स दिए गए हैं।
संक्षिप्त रूप (Compact Form)
अधिकांश इन्सर्ट क्वेरीज़ के लिए पसंदीदा रूप संक्षिप्त रूप है:
$result = $connection->insert('mytable')
->fields([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->getRequestTime(),
])
->execute();
यह निम्नलिखित क्वेरी के बराबर होगा:
INSERT INTO {mytable} (title, uid, created) VALUES ('Example', 1, 1221717405);
ऊपर दिया गया स्निपेट इन्सर्ट प्रक्रिया के प्रमुख हिस्सों को जोड़ता है।
$connection->insert('mytable')
यह लाइन mytable टेबल के लिए एक नया इन्सर्ट क्वेरी ऑब्जेक्ट बनाती है।
->fields([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->getRequestTime(),
])
fields() मेथड कई प्रकार के पैरामीटर्स स्वीकार करता है, लेकिन सबसे अधिक इस्तेमाल होने वाला तरीका एक एसोसिएटिव ऐरे है। ऐरे की कीज़ वे कॉलम होते हैं जिनमें वैल्यू डाली जाएगी, और वैल्यूज़ वे मान होते हैं जिन्हें डालना है। यह निर्दिष्ट टेबल पर एक इन्सर्ट क्वेरी का परिणाम देता है।
->execute();
execute() मेथड क्वेरी को चलाता है। यदि इसे कॉल नहीं किया जाता, तो क्वेरी नहीं चलती।
अन्य इन्सर्ट क्वेरी मेथड्स के विपरीत, जो खुद ऑब्जेक्ट लौटाते हैं, execute() एक ऑटो-इन्क्रीमेंट फ़ील्ड (या hook_schema() में परिभाषित sequence type) का मान लौटाता है, यदि ऐसा फ़ील्ड मौजूद हो। यही कारण है कि ऊपर के उदाहरण में इसका रिटर्न वैल्यू $result को असाइन किया गया है। यदि ऑटो-इन्क्रीमेंट फ़ील्ड नहीं है, तो execute() का रिटर्न वैल्यू परिभाषित नहीं है और उस पर भरोसा नहीं किया जाना चाहिए।
अधिकतर मामलों में यह इन्सर्ट क्वेरीज़ के लिए पसंदीदा रूप है।
विस्तृत रूप (Degenerate Form)
$result = $connection->insert('mytable')
->fields(['title', 'uid', 'created'])
->values([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->getRequestTime(),
])
->execute();
यह पिछले क्वेरी का अधिक विस्तृत रूप है और परिणाम बिल्कुल समान होगा।
->fields(['title', 'uid', 'created'])
जब fields() एक इंडेक्स्ड ऐरे के साथ कॉल किया जाता है, तो यह केवल उन कॉलम्स को सेट करता है जिन्हें क्वेरी में उपयोग किया जाएगा, लेकिन उनके लिए वैल्यू सेट नहीं करता। यह आगे चलकर मल्टी-रो इन्सर्ट करने के लिए उपयोगी है।
->values([
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->getRequestTime(),
])
यह मेथड कॉल फील्ड्स के लिए वैल्यूज़ का ऐरे सेट करता है। यह या तो एसोसिएटिव या इंडेक्स्ड ऐरे हो सकता है। यदि इंडेक्स्ड ऐरे उपयोग होता है, तो वैल्यूज़ का क्रम fields() में निर्दिष्ट फील्ड्स के क्रम से मेल खाना चाहिए। यदि एसोसिएटिव ऐरे उपयोग होता है, तो क्रम मायने नहीं रखता। पठनीयता के लिए सामान्यतः एसोसिएटिव ऐरे पसंद किया जाता है।
यह रूप दुर्लभ है, क्योंकि कॉम्पैक्ट रूप प्राथमिक होता है। अधिकतर मामलों में fields() और values() को अलग करने का एकमात्र कारण मल्टी-रो इन्सर्ट करना होता है।
मल्टी-इन्सर्ट रूप
इन्सर्ट क्वेरी ऑब्जेक्ट कई सेट्स के वैल्यूज़ भी ले सकता है। यानी values() को कई बार कॉल किया जा सकता है। यह डेटाबेस पर निर्भर करता है कि इन्हें कैसे हैंडल किया जाएगा। अधिकतर डेटाबेस में कई इन्सर्ट्स को ट्रांज़ैक्शन के भीतर चलाया जाता है ताकि डेटा इंटीग्रिटी और गति बनी रहे। MySQL में यह मल्टी-वैल्यू इन्सर्ट सिंटैक्स का उपयोग करता है।
$values = [
[
'title' => 'Example',
'uid' => 1,
'created' => \Drupal::time()->getRequestTime(),
],
[
'title' => 'Example 2',
'uid' => 1,
'created' => \Drupal::time()->getRequestTime(),
],
[
'title' => 'Example 3',
'uid' => 2,
'created' => \Drupal::time()->getRequestTime(),
],
];
$query = $connection->insert('mytable')->fields(['title', 'uid', 'created']);
foreach ($values as $record) {
$query->values($record);
}
$query->execute();
ऊपर दिए गए उदाहरण में तीन इन्सर्ट्स एक साथ चलेंगे, डेटाबेस ड्राइवर के सबसे प्रभावी तरीके का उपयोग करके। ध्यान दें कि यहाँ हमने क्वेरी ऑब्जेक्ट को वेरिएबल में सेव किया ताकि हम $values पर लूप कर सकें और values() को कई बार कॉल कर सकें।
यह साधारणतया निम्नलिखित तीन क्वेरीज़ के बराबर है:
INSERT INTO {mytable} (title, uid, created) VALUES ('Example', 1, 1221717405);
INSERT INTO {mytable} (title, uid, created) VALUES ('Example2', 1, 1221717405);
INSERT INTO {mytable} (title, uid, created) VALUES ('Example3', 2, 1221717405);
ध्यान दें कि मल्टी-इन्सर्ट क्वेरीज़ में execute() का रिटर्न वैल्यू परिभाषित नहीं है और उस पर भरोसा नहीं किया जाना चाहिए, क्योंकि यह ड्राइवर पर निर्भर करता है।
सेलेक्ट क्वेरी से इन्सर्ट
यदि आप अन्य टेबल्स के परिणामों से टेबल भरना चाहते हैं, तो आपके पास दो विकल्प हैं: SELECT करके डेटा को PHP में प्रोसेस करें और नई टेबल में इन्सर्ट करें, या INSERT INTO ... SELECT FROM क्वेरी का उपयोग करें, जिसमें SELECT क्वेरी से प्रत्येक पंक्ति को INSERT में डाला जाता है।
इस उदाहरण में हम mytable टेबल बनाना चाहते हैं जिसमें सिस्टम में सभी nodes के लिए nid और username हों, जिनका प्रकार "page" है।
<?php
// SELECT क्वेरी बनाएं।
$query = $connection->select('node', 'n');
// users टेबल से join करें।
$query->join('users', 'u', 'n.uid = u.uid');
// आवश्यक फील्ड्स जोड़ें।
$query->addField('n','nid');
$query->addField('u','name');
// केवल page nodes को प्राप्त करने की शर्त।
$query->condition('type', 'page');
// इन्सर्ट चलाएं।
$connection->insert('mytable')
->from($query)
->execute();
?>
डिफ़ॉल्ट वैल्यूज़
सामान्य परिस्थितियों में, यदि आप किसी फील्ड के लिए मान निर्दिष्ट नहीं करते और टेबल स्कीमा में डिफ़ॉल्ट मान दिया गया है, तो डेटाबेस स्वतः वही मान डाल देगा। लेकिन कभी-कभी आपको स्पष्ट रूप से डेटाबेस से डिफ़ॉल्ट मान उपयोग करने के लिए कहना पड़ता है। यह तब आवश्यक होता है जब आप पूरी पंक्ति के लिए सभी डिफ़ॉल्ट मानों का उपयोग करना चाहते हैं। किसी फील्ड के लिए डिफ़ॉल्ट मान का उपयोग करने के लिए useDefaults() मेथड है।
$query->useDefaults(['field1', 'field2']);
यह क्वेरी को बताता है कि field1 और field2 के लिए डिफ़ॉल्ट मान उपयोग करे। ध्यान दें कि यदि एक ही फील्ड useDefaults() और fields() या values() में निर्दिष्ट किया गया है, तो यह एक त्रुटि होगी और एक्सेप्शन फेंका जाएगा।
$connection->insert() या $connection->query()?
यह एक अक्सर पूछा जाने वाला प्रश्न है। (इस पेज पर टिप्पणियाँ देखें।) insert() और query() में क्या अंतर है?
insert() मेथड में प्रत्येक कॉलम को फील्ड ऐरे में अलग से निर्दिष्ट किया जाता है, और कोड प्रत्येक कॉलम वैल्यू को सुरक्षित रूप से संभाल सकता है। query() में एक SQL स्ट्रिंग होती है जिसमें व्यक्तिगत कॉलम की जाँच करने का विकल्प नहीं होता। यदि आप query() को प्लेसहोल्डर्स के साथ उपयोग करते हैं, तो कॉलम वैल्यूज़ की जाँच की जा सकती है, लेकिन प्लेसहोल्डर्स केवल एक विकल्प हैं और इस बात की गारंटी नहीं होती कि SQL स्ट्रिंग में कोई मान सीधे बिना प्लेसहोल्डर के न डाला गया हो।
insert() क्वेरी को हुक्स के सेट से गुजारता है, ताकि अन्य मॉड्यूल आपके क्वेरी की जाँच और संशोधन कर सकें। यह अन्य मॉड्यूल्स के साथ काम करने का सही तरीका है। query() थोड़ा तेज़ है, क्योंकि यह क्वेरी को हुक्स से नहीं गुजारता। आप प्रोसेसिंग समय बचा सकते हैं, लेकिन आपका कोड अन्य मॉड्यूल्स को सहयोग करने की अनुमति नहीं देगा।
insert() अन्य डेटाबेस और Drupal के भविष्य के संस्करणों के साथ अधिक काम करता है।