जैसा कि दूसरों ने पहले ही सुझाव दिया है, हम आम तौर पर से बचते हैं एक परिणाम सेट के माध्यम से लूपिंग RBAR (पंक्ति को पीड़ा देने वाली पंक्ति) मुख्य रूप से प्रदर्शन कारणों से। हम परिणामसेट के माध्यम से लूप करने की आदत में नहीं आना चाहते हैं। लेकिन यह आपके द्वारा पूछे गए प्रश्न का उत्तर नहीं देता है।
आपके द्वारा पूछे गए प्रश्न का उत्तर देने के लिए, यहां एक MySQL संग्रहीत प्रोग्राम का एक प्रारंभिक उदाहरण दिया गया है जो एक क्वेरी द्वारा लौटाई गई पंक्तियों को व्यक्तिगत रूप से संसाधित करने के लिए CURSOR का उपयोग करता है। MySQL अनाम ब्लॉकों का समर्थन नहीं करता है, इसलिए ऐसा करने का एकमात्र तरीका एक MySQL संग्रहीत प्रोग्राम में है, जैसे PROCEDURE
DELIMITER $$
CREATE PROCEDURE loop_through_var_list
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_id INT DEFAULT NULL;
DECLARE csr_var_list CURSOR FOR SELECT id FROM var_list ORDER BY id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN csr_var_list;
get_id: LOOP
FETCH csr_var_list INTO v_id;
IF done = 1 THEN
LEAVE get_id;
END IF;
-- at this point, we have an id value in v_id, so we can do whatever
SET @s1 = CONCAT('SELECT ... WHERE id =''', v_id, ''' ...');
END LOOP get_id;
CLOSE csr_var_list;
END$$
DELIMITER ;
प्रक्रिया निष्पादित करने के लिए:
CALL loop_through_var_list();
नोट:MySQL में CURSOR को प्रोसेस करने के लिए सिंटैक्स अन्य डेटाबेस से काफी अलग है।
"लूपिंग" प्राप्त करने के लिए, हमें LOOP ... END LOOP
. का उपयोग करने की आवश्यकता है निर्माण।
लेकिन उस लूप को हमेशा के लिए चलने से रोकने के लिए, हमें एक LEAVE स्टेटमेंट चाहिए जो हमें लूप से बाहर निकलने की अनुमति देगा।
कब जाना है यह निर्धारित करने के लिए हम एक सशर्त परीक्षण का उपयोग करते हैं। इस उदाहरण में, हम अंतिम पंक्ति को संसाधित करने के बाद बाहर निकलना चाहते हैं।
FETCH
जब कोई और पंक्तियाँ प्राप्त करने के लिए नहीं हैं, तो एक अपवाद फेंकने जा रहा है।
हम एक कॉन्टिन्यू हैंडलर में उस अपवाद को "पकड़" लेते हैं (कुछ रहस्यमय कारणों से, "हैंडलर" को घोषित अंतिम चीजें होती हैं; अगर हम हैंडलर (दूसरे हैंडलर के अलावा) के बाद कुछ घोषित करने का प्रयास करते हैं तो MySQL एक त्रुटि फेंकता है।
जब MySQL "कोई और पंक्तियाँ नहीं" अपवाद फेंकता है, जो हैंडलर कोड को सक्रिय करता है। इस उदाहरण में, हम केवल एक वैरिएबल सेट कर रहे हैं (नाम done
) एक मूल्य के लिए।
चूंकि यह एक "जारी रखें" हैंडलर है, प्रसंस्करण उस कथन पर बैक अप शुरू होता है जहां अपवाद फेंक दिया गया था, इस मामले में, यह FETCH के बाद का बयान होगा। इसलिए, सबसे पहले हम यह जांचते हैं कि हम "किया" गए हैं या नहीं। अगर हम "किया" कर चुके हैं, तो हम लूप से बाहर निकल जाते हैं, और कर्सर को बंद कर देते हैं।
अन्यथा, हम जानते हैं कि हमारे पास एक id
है var_list
. से मान v_id
. नामक एक प्रक्रिया चर में संग्रहीत . इसलिए अब हम जो चाहें कर सकते हैं। ऐसा लगता है कि आप कुछ SQL टेक्स्ट को यूज़र-डिफ़ाइंड वेरिएबल में रखना चाहते हैं (जिसमें SQL टेक्स्ट में v_id का मान शामिल है, फिर PREPARE, EXECUTE, और DEALLOCATE PREPARE।
v_id
. घोषित करना सुनिश्चित करें उपयुक्त डेटाटाइप के साथ वेरिएबल, जो id
. के डेटाटाइप से मेल खाता है var_list
में कॉलम , मैंने अभी-अभी माना है कि यह एक INT है।
जब हम लूप के अंत तक पहुँचते हैं, तो MySQL "लूप" लूप की शुरुआत में वापस आ जाता है, और हम फिर से चले जाते हैं।
लूप के मुख्य भाग में, संभावना है कि आप उस SQL पाठ में v_id को CONCAT करना चाहेंगे जिसे आप निष्पादित करना चाहते हैं। ऐसा लगता है कि आपके पास PREPARE, DEALLOCATE तैयारी पर पहले से ही एक हैंडल है। परीक्षण के लिए, आप कर्सर घोषणा में SELECT पर एक LIMIT क्लॉज जोड़ना चाह सकते हैं, और फिर एक साधारण SELECT v_id कर सकते हैं; अधिक कोड जोड़ने से पहले, शरीर में, बस यह सत्यापित करने के लिए कि लूप काम कर रहा है।
अनुसरण करें
मैं कार्य के लिए एक और वैकल्पिक दृष्टिकोण का उल्लेख करना चाहता था, यानी एक टेम्पलेट के आधार पर बयानों की एक श्रृंखला चलाना, एक एकल SQL चयन कथन से प्रदान किए गए मानों को प्रतिस्थापित करना...
उदाहरण के लिए, यदि मेरे पास यह टेम्पलेट था:
SELECT *
INTO OUTFILE '/tmp/[email protected]'
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM data
WHERE id = @ID
ORDER BY 1
और मुझे एक चयन कथन से लौटाई गई सूची से एक विशिष्ट आईडी मान के साथ @ID की घटनाओं को प्रतिस्थापित करने की आवश्यकता है, उदा।
SELECT id
FROM var_list
WHERE id IS NOT NULL
GROUP BY id
मैं शायद एक कर्सर लूप के साथ एक MySQL संग्रहीत प्रोग्राम का उपयोग नहीं करूंगा, मैं एक अलग दृष्टिकोण का उपयोग करूंगा।
मैं SQL कथनों का एक सेट उत्पन्न करने के लिए एक चयन कथन का उपयोग करता हूं जिसे निष्पादित किया जा सकता है। मान लें कि id
पूर्णांक प्रकार है, मैं संभवतः कुछ ऐसा करूंगा:
SELECT CONCAT(' SELECT *
INTO OUTFILE ''/tmp/orders_',s.id,'.csv''
FIELDS TERMINATED BY '','' ENCLOSED BY ''"''
LINES TERMINATED BY ''\n''
FROM data
WHERE id = ',s.id,'
ORDER BY 1;') AS `stmt`
FROM ( SELECT v.id
FROM var_list v
WHERE v.id IS NOT NULL
GROUP BY v.id
) s
ORDER BY s.id
id
. के हर मान के लिए s
. से लौटा , कथन SQL SELECT कथन का पाठ देता है जो निष्पादित (और करने की आवश्यकता) कर सकता है। इसे एक टेक्स्ट फ़ाइल में कैप्चर करने से मुझे एक SQL स्क्रिप्ट मिलेगी जिसे मैं चला सकता था।