यदि मैं इसे नहीं छोड़ता तो कब तक एक अस्थायी स्मृति तालिका बनी रहेगी (MySQL)


13

मैं MySQL में एक पुनरावर्ती संग्रहित प्रक्रिया का उपयोग कर रहा हूं id_list, जिसे एक अस्थायी तालिका कहा जाता है , लेकिन मुझे उस प्रक्रिया के परिणामों का चयन अनुवर्ती क्वेरी में करना चाहिए, इसलिए मैं DROPप्रक्रिया के भीतर अस्थायी तालिका नहीं बना सकता ...

BEGIN;

/* generates the temporary table of ID's */
CALL fetch_inheritance_groups('abc123',0);

/* uses the results of the stored procedure in the WHERE */
SELECT a.User_ID
FROM usr_relationships r 
INNER JOIN usr_accts a ON a.User_ID = r.User_ID 
WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list) 
GROUP BY r.User_ID;

COMMIT;

प्रक्रिया को कॉल करते समय, पहला मान उस शाखा का शीर्ष आईडी है जो मैं चाहता हूं, और दूसरा वह है tierजो प्रक्रिया पुनरावृत्ति के दौरान उपयोग करती है। पुनरावर्ती लूप से पहले यह जांचता है कि क्या tier = 0और अगर यह चलता है:

DROP TEMPORARY TABLE IF EXISTS id_list;
CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;

तो मेरा सवाल है: अगर मैं प्रक्रिया के अंत में, या अपने लेन-देन के भीतर DROPअस्थायी MEMORYतालिका नहीं रखता हूं, तो वह तालिका कितनी देर तक स्मृति में बनी रहेगी? एक बार सत्र समाप्त होने के बाद क्या यह स्वचालित रूप से गिरा दिया जाता है, या जब तक कनेक्शन खुला रहता है, तब तक यह मेमोरी में बना रहेगा?

** एनबी स्पष्ट कथन के बयान से पहले अस्थायी तालिका को छोड़ने के लिए हो सकता है, लेकिन एक पल के लिए मान लेता है कि मैं ऐसा नहीं कर सकता। *


संपादित करें : थोड़ा और सटीक होने के लिए, यदि निरंतर कनेक्शन कार्यरत हैं, तो क्या तालिका कई अनुरोधों के माध्यम से बनी रहेगी? अब तक ऐसा लगता है कि यह और उस संसाधन को मुक्त करने के लिए हमें स्पष्ट रूप से अस्थायी तालिका को हटाने की आवश्यकता होगी।


अद्यतन : टिप्पणीकारों की सलाह के आधार पर, मैंने अपनी संग्रहीत प्रक्रिया को समायोजित करने का एक तरीका ढूंढ लिया है ताकि मैं TEMP मेमोरी तालिका का उपयोग कर सकूं, लेकिन DROPअंत में इसे स्पष्ट रूप से सक्षम कर सकूं ...

केवल संग्रहीत कार्यविधि को कॉल करने और वास्तविक क्वेरी में परिणाम एकत्र करने के लिए शेष TEMP तालिका का उपयोग करने के बजाय, मैंने इस तरह CALLएक तीसरे OUTचर का उपयोग करने के लिए प्रारूप को बदल दिया है:

CALL fetch_inheritance_groups('abc123','0',@IDS);

... तो संग्रहीत प्रक्रिया के भीतर, मैंने IF tier = 0निम्नलिखित के साथ बहुत अंत में एक दूसरा जोड़ा :

IF tier = 0
    THEN
    SELECT GROUP_CONCAT(DISTINCT iid SEPARATOR ',') FROM id_list INTO inherited_set;
    DROP TEMPORARY TABLE IF EXISTS id_list;
END IF;

तो संग्रहीत प्रक्रिया का परिणाम अब आईडी की एक अल्पविराम से अलग सूची है जो संगत है FIND_IN_SET, और इसलिए अंतिम क्वेरी को संशोधित किया गया था:

WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list)

... अब है ...

WHERE r.Group_ID = 'abc123' OR FIND_IN_SET(r.Group_ID,@IDS)

देखा! आपके इनपुट के लिए टिप्पणीकारों के लिए धन्यवाद, और मुझे कारण देने के लिए मुझे थोड़ा कठिन प्रयास करने की आवश्यकता थी :)

जवाबों:


17

किसी संग्रहीत कार्यविधि में अस्थायी तालिकाओं के बारे में जो अजीब बात है वह तालिका के क्षणिक अस्तित्व (जो DB कनेक्शन की समाप्ति पर गिरा दी जाती है) की नहीं है, लेकिन संग्रहीत कार्यविधि की गुंजाइश है।

StackOverflow पर किसी ने यह प्रश्न पूछा था: MySQL में निर्मित टेम्पर टेबल्स का स्कोप संग्रहीत कार्यविधि । एक साल से अधिक हो गया है और किसी ने भी सवाल का जवाब नहीं दिया? मुझे सीधे रिकॉर्ड सेट करने दो। तथ्य यह है: टेम्पर्ड टेबल स्टोर्ड प्रक्रिया के अंदर और बाहर मौजूद है, लेकिन आप अस्थायी टेबल के साथ चीजें केवल एक रनिंग स्टोर्ड प्रोसीजर के दायरे में कर सकते हैं ।

पुस्तक के अनुसार

kdsjx

अध्याय 5 में एक और संग्रहित प्रक्रिया के लिए एक शानदार रिटर्निंग सेट है

यह पेज 117 पर पैराग्राफ 2 में कहता है:

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

पर वापस देख रहे हैं StackOverflow सवाल , मैं किसी mysql ग्राहक से संग्रहित प्रक्रिया कहा जाता है देख सकते हैं। चूंकि mysql क्लाइंट एक संग्रहीत प्रक्रिया नहीं है, इसलिए परिणामों को देखने के लिए चयन का चयन करने के अलावा DML के माध्यम से mysql क्लाइंट स्तर में हेरफेर नहीं किया जा सकता है। चूंकि आप एक पुनरावर्ती संग्रहित प्रक्रिया को बुला रहे हैं, इसलिए आप आश्वस्त हो सकते हैं कि डीबी कनेक्शन की अवधि के लिए अस्थायी तालिका पूरी तरह से सुलभ है

हम उम्मीद करते है कि यह आपके सवाल का जवाब दे देगा।

अद्यतन 2014-01-31 11:26 ईएसटी

अपनी अंतिम टिप्पणी में, आपने कहा

यदि हम लगातार कनेक्शन नियोजित करते हैं, तो मेमरी टेबल कई REQUESTS के माध्यम से बनी रहेगी, और ऐसा लगता है कि ऐसा होगा, इसलिए प्रदर्शन के लिए, मैं यह मान रहा हूं कि इस पद्धति का उपयोग करना * हमें अस्थायी मेमोरियल तालिका को स्पष्ट रूप से DROP करने के लिए बताएगा। क्या मैं सही तरीके से मान लेता हूं?

हां और नहीं, मैं हां कहता हूं क्योंकि यह एक तरीका है। मैं नहीं कहता क्योंकि ऐसा करने का एक और तरीका है:

CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;
TRUNCATE TABLE id_list;

आप जो भी रास्ता चुनते हैं, ऑपरेशन अभी भी उसी तरह से है क्योंकि ट्रिब्यूट टेबल ड्रॉप हो जाता है और तालिका को फिर से बनाता है। यह अन्य DB कनेक्शंस को नुकसान नहीं पहुंचाएगा क्योंकि प्रत्येक कनेक्शन की अपनी id_list तालिका होती है।


बहुत सराहना की Rolando! मैंने एसओ ( stackoverflow.com/questions/21483448/… ) पर एक ही सवाल पोस्ट किया, बस अगर उस पर अधिक नजरें मिलीं, और मैं कम जानकारीपूर्ण, उत्तर के समान, मिला। मैंने एक अनुवर्ती कार्रवाई की: यदि हम लगातार कनेक्शन का उपयोग करते हैं, तो क्या मेमोरी टेबल कई अनुरोधों के माध्यम से बनी रहेगी, और ऐसा लगता है, इसलिए प्रदर्शन के लिए, मैं यह मान रहा हूं कि इस पद्धति का उपयोग करना * हमें स्पष्ट रूप DROPसे अस्थायी मेमोरी की आवश्यकता होगी तालिका। क्या मैं सही तरीके से मान लेता हूं?
उसिल

आपके अद्यतन के संबंध में, मुझे लगता है कि मैं एक संसाधन को छोड़ने के संबंध में अधिक चिंतित हूं जो अब उस क्वेरी तक चलने तक आवश्यक नहीं है, और मुझे लगता है कि यह अधिक स्पष्ट हो रहा है कि मुझे यह स्पष्ट रूप से हटा देना चाहिए कि क्या मैं डॉन ' t की जरूरत है।
उसिल

" दुर्भाग्य से, एक संग्रहीत प्रक्रिया से दूसरे में सेट किए गए परिणाम को पारित करने का एकमात्र तरीका अस्थायी तालिका के माध्यम से परिणाम पारित करना है " । क्या इसका मतलब यह है कि हम रिजल्ट सेट (कॉलर से) का उपयोग तभी कर सकते हैं जब हमें अस्थायी तालिका का नाम पता हो जो कि कार्यविधि में बनाई गई है? क्या रिजल्ट सेट को पढ़ने का एक तरीका नहीं है, जैसे हम SELECTसंग्रहीत प्रक्रियाओं में एक स्टेटमेंट के परिणाम सेट को पढ़ने के लिए उपयोग कर सकते हैं DECLARE aCursor CURSOR FOR SELECT ...? ई। जी। DECLARE theCursor CURSOR FOR CALL aProcedure()?
मीर-इस्माइली

2

अधिकांश DBMS में अस्थायी टेबल वर्तमान कनेक्शन के अंत तक जीवित रहती हैं जब तक कि अन्यथा निर्दिष्ट न हो या जब तक कि कोई स्पष्ट लेन-देन रोलबैक न हो (कुछ सिस्टम में रोलबैक केवल तालिका की सामग्री को प्रभावित कर सकता है, यदि आवश्यक हो तो ऑब्जेक्ट को फिर से दोहराया जा सकता है) । तालिका (डिफ़ॉल्ट रूप से) अन्य कनेक्शनों के लिए दृश्यमान नहीं होगी, भले ही वह कनेक्शन कितना समय तक रहता हो।

Google पर एक त्वरित स्कैन यह इंगित करता है कि यह कैसे mySQL संचालित होता है।
( http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm "डिफ़ॉल्ट रूप से, सभी अस्थायी तालिकाएँ MySQL द्वारा हटा दी जाती हैं जब आपका डेटाबेस कनेक्शन समाप्त हो जाता है")

हालांकि इन व्यवहारों को बदलने के कई तरीके हैं। उदाहरण के लिए MS SQL सर्वर में आप एक अस्थायी तालिका बना सकते हैं, जो कि ## शुरू करने वाले नाम देकर, केवल वर्तमान एक के बजाय सभी कनेक्शनों को दिखाई दे।

मैं हमेशा अस्थायी तालिकाओं को छोड़ देता हूं जैसे ही वे संभव भ्रम से बचने के लिए आवश्यक नहीं होते हैं। मुझे पहले काट दिया गया है जहां कनेक्शन पूलिंग के कारण अस्थायी तालिका निर्माण में त्रुटि हुई क्योंकि उसी नाम की एक अस्थायी तालिका बनाई गई थी, लेकिन पिछले कनेक्शन में नष्ट नहीं हुई थी जो वर्तमान कनेक्शन का उपयोग करती थी।


मैं सहमत हूं कि मुझे तालिका को स्पष्ट रूप से छोड़ने का एक तरीका ढूंढना चाहिए, लेकिन DROPप्रारंभिक टीयर आईएफ के भीतर पुन: निर्माण करने से पहले आपके द्वारा समाप्त किए गए मुद्दे के आसपास मैं इसे प्राप्त करता हूं । आपके सहयोग के लिए धन्यवाद!
उसिल

-2
CREATE TEMPORARY TABLE  IF NOT EXISTS temp (Months VARCHAR(50),Sequence INT)
AS (
SELECT 
CONCAT(MONTHNAME(m1),' ',YEAR(m1)) AS Months,CONVERT(m1,DATE) AS Sequence
FROM
(
SELECT 
('2014-01-01' - INTERVAL DAYOFMONTH('2014-01-01')-1 DAY) 
+INTERVAL m MONTH AS m1
FROM
(
SELECT @rownum:=@rownum+1 AS m FROM
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t1,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t2,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t3,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t4,
(SELECT @rownum:=-1) t0
) d1
) d2 
WHERE m1<= '2015-07-30'
ORDER BY m1
) ;

SELECT t.Months,A.OpenCount,A.CloseCount FROM Temp T
 LEFT JOIN ( SELECT  CONCAT(MONTHNAME(e.dtcdate),' ',YEAR(e.dtcdate)) AS Months,
 ( SELECT  COUNT(csr.ddlcsstatus) FROM csrcrn_frmempengagreqs csr 
 JOIN master_detail md ON md.masterDetailId=csr.ddlcsstatus WHERE md.abbr='open' AND csr.dtcdate >='2014-01-01' AND csr.dtcdate <='2015-07-30' AND csr.ddlArea=e.ddlArea ) AS OpenCount
 ,
 ( SELECT  COUNT(csr.ddlcsstatus) FROM csrcrn_frmempengagreqs csr 
 JOIN master_detail md ON md.masterDetailId=csr.ddlcsstatus WHERE md.abbr='Close' AND csr.dtcdate >='2014-01-01' AND csr.dtcdate <='2015-07-30' AND csr.ddlArea=e.ddlArea ) AS CloseCount

 FROM csrcrn_frmempengagreqs e 
 INNER JOIN master_detail m ON e.ddlcsstatus=m.masterDetailId 
  WHERE  e.dtcdate >='2014-01-01' AND e.dtcdate <='2015-07-30' 
 GROUP BY MONTH(e.dtcdate) ORDER BY e.dtcdate 
 ) A ON CONVERT(A.Months,CHAR(20))=CONVERT(T.Months,CHAR(20)) 
       ORDER BY T.Sequence; 
       DROP TEMPORARY TABLE  IF EXISTS temp;

/ * दिया गया क्वेरी सफलतापूर्वक परिणाम देता है ... जब इस क्वेरी को यूएसपी में डाल दिया जाता है तो त्रुटि plz मेरी मदद करता है..प्रो नीचे दी गई है / /

DELIMITER $$

DROP PROCEDURE IF EXISTS `usp_GetEngMonthlyChart_Test`$$

CREATE DEFINER=`root`@`%` PROCEDURE `usp_GetEngMonthlyChart_Test`(IN DateFrom DATE,IN DateTo DATE)
BEGIN
      -- SET @strWhere= CONCAT(' AND CSR.dtcInductionDate BETWEEN ''',CONVERT(DateFrom,DATE),''' AND ','''',CONVERT(DateTo,DATE),''''); 


    SET @strSql=CONCAT(' 

    CREATE TEMPORARY TABLE  IF NOT EXISTS temp (Months VARCHAR(50),Sequence INT)
    AS (
    SELECT 
    CONCAT(MONTHNAME(m1),'' '',YEAR(m1)) AS Months,CONVERT(m1,DATE) AS Sequence
    FROM
    (
    SELECT 
    (''',DateFrom,''' - INTERVAL DAYOFMONTH(''',DateFrom,''')-1 DAY) 
    +INTERVAL m MONTH AS m1
    FROM
    (
    SELECT @rownum:=@rownum+1 AS m FROM
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t1,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t2,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t3,
    (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t4,
    (SELECT @rownum:=-1) t0
    ) d1
    ) d2 
    WHERE m1<= ''',DateTo,'''
    ORDER BY m1
    )' );   

         SET @strSql=CONCAT(@strSql,'; GO SELECT t.Months,A.OpenCount,A.CloseCount FROM Temp T
     LEFT JOIN ( SELECT  CONCAT(MONTHNAME(e.dtcdate),'' '',YEAR(e.dtcdate)) AS Months,
     ( SELECT  COUNT(csr.ddlcsstatus) FROM csrcrn_frmempengagreqs csr 
     JOIN master_detail md ON md.masterDetailId=csr.ddlcsstatus WHERE md.abbr=''open'' AND csr.dtcdate >=''',DateFrom,
     ''' AND csr.dtcdate <=''',DateTo,''' AND csr.ddlArea=e.ddlArea ) AS OpenCount
     ,
     ( SELECT  COUNT(csr.ddlcsstatus) FROM csrcrn_frmempengagreqs csr 
     JOIN master_detail md ON md.masterDetailId=csr.ddlcsstatus WHERE md.abbr=''Close'' AND csr.dtcdate >=''',DateFrom,
     ''' AND csr.dtcdate <=''',DateTo,''' AND csr.ddlArea=e.ddlArea ) AS CloseCount

     FROM csrcrn_frmempengagreqs e 
     INNER JOIN master_detail m ON e.ddlcsstatus=m.masterDetailId 
      WHERE  e.dtcdate >=''',DateFrom,''' AND e.dtcdate <=''',DateTo,''' 
     GROUP BY MONTH(e.dtcdate) ORDER BY e.dtcdate 
     ) A ON CONVERT(A.Months,CHAR(20))=CONVERT(T.Months,CHAR(20)) 
           ORDER BY T.Sequence; 
           DROP TEMPORARY TABLE  IF EXISTS temp;'); 

    SELECT @strSql;
    PREPARE stmt FROM @strSql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END$$

DELIMITER ;

कॉल usp_GetEngMonthlyChart_Test ('2014-01-01', '2015-07-30')


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