एक ट्रिगर से संग्रहीत प्रक्रिया को कॉल करें


17

मैंने निम्नलिखित सिंटैक्स का उपयोग करके mysql में एक संग्रहीत प्रक्रिया बनाई है।

DROP PROCEDURE IF EXISTS `sp-set_comment_count`;

DELIMITER $$

CREATE PROCEDURE `sp_set-comment_count` (IN _id INT)
BEGIN
   -- AC   - AllCount
   DECLARE AC INT DEFAULT 0;

   SELECT COUNT(*) AS ac
     INTO AC
     FROM usergroups AS ug
LEFT JOIN usergroup_comments AS ugm ON ugm.`gid` = ug.`id`
LEFT JOIN mediagallery AS dm ON ugm.mid = dm.`id`
    WHERE dm.`status` NOT IN (200, 201, 202, 203, 204, 205)
      AND ug.`id` = _id;

   UPDATE usergroups
      SET allCount = AC,
    WHERE usergroups.`id` = _id;

END $$
DELIMITER ;

FYI करें मैंने संग्रहीत प्रक्रिया को बहुत सरल कर दिया है, लेकिन मुझे पता है कि यह बिना किसी समस्या के काम करता है।

मैं ऐसा करने में सक्षम होना चाहूंगा कि उपयोगकर्ता समूह से एक ट्रिगर सेट किया जाए जो इस तरह से काम करता है।

DROP TRIGGER IF EXISTS `usergroups_comments_insert` 

CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
    FOR EACH ROW
    BEGIN
       CALL sp-set-comment_count(NEW.`gid`);
    END;

लेकिन हर बार किसी कारण से मैं mysql मुझ पर एक त्रुटि फेंकता है जो कि उपयोगी बताते हुए कम से कम है कि पंक्ति 4 पर एक सिंटैक्स त्रुटि है।

मैंने mysql प्रलेखन के माध्यम से कंघी की है और ट्रिगर्स के प्रतिबंधों के बारे में कुछ जानकारी प्राप्त की है लेकिन यह काफी जटिल पाया गया है।

http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html

कोई भी विचार मददगार होगा।


तो यह समस्या को बताता है कि ऊपर संग्रहीत प्रक्रिया के साथ समस्या यह है कि यह नाम में एक हाइफ़न था तथ्य यह है। संग्रहीत कार्यविधि का नाम बदलकर sp_set_comment_count करने से समस्या हल हो गई।
मार्क डी

जवाबों:


24

इस बात का बहुत बड़ा कारण है कि आपको ट्रिगर्स के भीतर से संग्रहीत प्रक्रियाओं को कभी नहीं कॉल करना चाहिए।

ट्रिगर प्रकृति द्वारा, संग्रहीत प्रक्रियाएं हैं। उनके कार्यों को वापस रोल करना लगभग कठिन है । यहां तक ​​कि अगर सभी अंतर्निहित तालिकाओं में InnoDB है, तो आप विशेष पंक्ति ताले से साझा पंक्ति ताले और कष्टप्रद आंतरायिक अनुपात का अनुभव करेंगे। ऐसा तब होगा जब ट्रिगर INSERTs और UPDATEs के साथ तालिकाओं में हेरफेर कर रहे थे ताकि ट्रिगर के लिए प्रत्येक कॉल के अंदर भारी शुल्क MVCC प्रदर्शन किया जा सके

मत भूलो कि ट्रिगर को ओवरहेड की आवश्यकता है। वास्तव में, के अनुसार MySQL संग्रहीत कार्यविधि प्रोग्रामिंग के , सिर के नीचे पेज 256 "ट्रिगर ओवरहेड" निम्नलिखित कहता है:

यह याद रखना महत्वपूर्ण है कि, आवश्यकता से, ट्रिगर ओवरहेड को डीएमएल स्टेटमेंट में जोड़ते हैं, जिस पर वे लागू होते हैं। ओवरहेड की वास्तविक मात्रा ट्रिगर की प्रकृति पर निर्भर करेगी, लेकिन --- जैसा कि सभी MySQL ट्रिगर EOW ROW के लिए निष्पादित करते हैं --- ओवरहेड बड़ी संख्या में पंक्तियों को संसाधित करने वाले बयानों के लिए तेजी से जमा हो सकता है। इसलिए आपको ट्रिगर में कोई भी महंगा SQL स्टेटमेंट या प्रक्रियात्मक कोड रखने से बचना चाहिए।

ट्रिगर ओवरहेड का एक विस्तृत विवरण पृष्ठ 529-531 पर दिया गया है। उस अनुभाग से समापन बिंदु निम्नलिखित बताता है:

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

मैंने पहले के पोस्ट में ट्रिगर्स के अन्य बुरे पहलुओं को समझाया।

सारांश

मैं दृढ़ता से किसी भी संग्रहीत प्रक्रियाओं को ट्रिगर से नहीं बुलाने की सलाह दूंगा , भले ही MySQL इसे अनुमति देता हो। आपको MySQL 5.5 के लिए वर्तमान प्रतिबंधों की जाँच करनी चाहिए


दिलचस्प है, सिर के लिए धन्यवाद। हमारे वातावरण में लेन-देन संबंधी प्रश्नों की कमी लेनदेन के मुद्दे को कम करती है। हालांकि मैं उपरि संचय के विचार की सराहना कर सकता हूं। मुझे लगता है कि मैं थोड़ी देर के लिए डीबी देखूंगा कि इस परिवर्तन का परिणाम क्या है।
मार्क डी

मुझे नहीं लगता कि संग्रहीत प्रक्रियाओं के साथ ट्रिगर को भ्रमित करना सटीक है। न्यूनतम पर, यह एक संग्रहीत प्रक्रिया में लेनदेन शुरू करने और करने के लिए वैध है। यदि आप ट्रिगर में भी ऐसा करने की कोशिश करते हैं तो MySQL शिकायत करता है। जो मूर्खतापूर्ण है, क्योंकि कुछ परिवर्तन के जवाब में एक या अधिक तालिकाओं को लेन-देन को अद्यतन करने की आवश्यकता वाले ट्रिगर को पूरी तरह से मान्य उपयोग-मामला है जिसे सीधे तरीके से समर्थन किया जाना चाहिए।
अरोठ

इसलिए मेरे पास यह ट्रिगर है, जो वास्तव में बहुत बड़ा है। यह मेरी मेज पर कई गणनाएं करता है, दोनों सम्मिलित और अद्यतन पर। जब वे जटिल होते हैं तो मैसकल में ट्रिगर वास्तव में दर्दनाक हो सकते हैं। प्रक्रियाओं में ट्रिगर को तोड़ना बहुत आसान होगा।
लैमर

8

इसलिए यह पता चला कि यह मुद्दा है जिसने मुझे कुछ घंटों के लिए त्रस्त कर दिया है या नहीं।

मैं आसानी से, sp_set-comment_count नामक एक प्रक्रिया को परिभाषित कर सकता हूं। हालाँकि जब कॉलिंग प्रक्रिया कहा जाता है, तो यह उसी तरह से काम नहीं करता है।

कॉल sp_set-comment_count (मैं केवल यह मान सकता हूं क्योंकि सर्वर - को एक ऋण के रूप में व्याख्या करता है)।

मैंने तब से संग्रहीत प्रक्रिया नाम को केवल अंडरस्कोर का उपयोग करने के लिए बदल दिया है और ऐसा लगता है कि सब कुछ हल हो गया है।


देर पार्टी के लिए लेकिन: यदि आप अपने सपा एक उद्धृत पहचानकर्ता है, जो अपने नाम में विशेष वर्णों की अनुमति का उपयोग कर बनाया है, तो आप इसे का उल्लेख होना चाहिए इसी तरह कहीं और:CALL `sp-set-comment_count`(NEW.`gid`);
mustaccio

5

यदि यह सिंटैक्स त्रुटि के बारे में कहता है, तो सबसे अधिक संभावना है कि आप सीमांकक को बदलना भूल गए (जैसा कि आपने संग्रहीत प्रक्रिया के लिए किया था)। तो आपको जरूरत है

DELIMITER $$
CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
FOR EACH ROW
BEGIN
   CALL sp_set_count(NEW.`gid`);
END;
$$

धन्यवाद, यह वास्तव में मुझे सही रास्ते पर सोचने के लिए मिला। वास्तव में मेरे sp को sp-set_comment_count कहा जाता था। जब ट्रिगर द्वारा कॉल किया जाता है, तो ऐसा प्रतीत होता है कि समस्या यह थी कि ट्रिगर से एसपी को कॉल करते समय - त्रुटि फेंकते रहे।
मार्क डी

1

ACसिंटैक्स त्रुटि के बाद कॉमा जैसा दिखता है:

UPDATE usergroups
   SET allCount = AC,
 WHERE ........

मान्य बिंदु, लेकिन इस मामले में त्रुटि का वास्तविक कारण नहीं है कि मैंने बस उस क्वेरी से कुछ अतिरिक्त सेटों को छाँट लिया और हटाने के लिए भूल गया,
मार्क डी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.