PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

फ़ंक्शन से टेक्स्ट आउटपुट को नई क्वेरी के रूप में उपयोग करें

PREPARE . के साथ ट्रिक काम नहीं करता है, क्योंकि यह CREATE FUNCTION जैसे * टेक्स्ट स्ट्रिंग* (एक मान) नहीं लेता है करता है, लेकिन एक मान्य कथन (कोड)।

डेटा को बदलने के लिए निष्पादन योग्य कोड . में आपको गतिशील SQL का उपयोग करने की आवश्यकता है, अर्थात EXECUTE plpgsql फ़ंक्शन में या DO . में बयान। यह बिना किसी समस्या के तब तक काम करता है जब तक रिटर्न प्रकार पहले फ़ंक्शन myresult() के परिणाम पर निर्भर नहीं करता है। . अन्यथा आप मेरे पिछले उत्तर में उल्लिखित 22 को पकड़ने के लिए वापस आ गए हैं:

  • पोस्टग्रेज में संग्रहीत कार्यविधि के स्ट्रिंग परिणाम को कैसे निष्पादित करें

महत्वपूर्ण हिस्सा है रिटर्न प्रकार घोषित करना (इस मामले में पंक्ति प्रकार) किसी तरह। आप एक TABLE बना सकते हैं , TEMP TABLE या TYPE उद्देश्य के लिए। या आप तैयार किए गए कथन या रिफ़कर्सर का उपयोग कर सकते हैं।

तैयार कथन के साथ समाधान

आप बहुत करीब रहे हैं। पहेली का गायब टुकड़ा डायनामिक SQL के साथ जेनरेट की गई क्वेरी तैयार करना है ।

कथन गतिशील रूप से तैयार करने का कार्य

यह फ़ंक्शन बनाएं एक बार . यह आपके फ़ंक्शन का एक अनुकूलित और सुरक्षित संस्करण है myresult() :

CREATE OR REPLACE FUNCTION f_prep_query (_tbl regclass, _prefix text)
  RETURNS void AS 
$func$
BEGIN
   IF EXISTS (SELECT 1 FROM pg_prepared_statements WHERE name = 'stmt_dyn') THEN
      DEALLOCATE stmt_dyn;
   END IF;                 -- you my or may not need this safety check 

   EXECUTE (
     SELECT 'PREPARE stmt_dyn AS SELECT '
         || string_agg(quote_ident(attname), ',' ORDER BY attname)
         || ' FROM ' || _tbl
      FROM   pg_catalog.pg_attribute
      WHERE  attrelid = _tbl
      AND    attname LIKE _prefix || '%'
      AND    attnum > 0
      AND    NOT attisdropped
     );
END
$func$  LANGUAGE plpgsql;

मैं regclass . का उपयोग करता हूं तालिका नाम पैरामीटर के लिए _tbl इसे SQLi के विरुद्ध स्पष्ट और सुरक्षित बनाने के लिए। विवरण:

  • तालिका नाम PostgreSQL फ़ंक्शन पैरामीटर के रूप में

सूचना स्कीमा में सिस्टम कैटलॉग का ओड कॉलम शामिल नहीं है, इसलिए मैंने pg_catalog.pg_attribute पर स्विच किया information_schema.columns . के बजाय . वह भी तेज है। इसके पक्ष और विपक्ष हैं:

  • किसी दिए गए स्कीमा में तालिका मौजूद है या नहीं, इसकी जांच कैसे करें

अगर stmt_dyn . नाम से तैयार किया गया स्टेटमेंट पहले से मौजूद है, PREPARE एक अपवाद उठाएगा। यदि यह स्वीकार्य है, तो सिस्टम दृश्य pg_prepared_statements . पर लगे चेक को हटा दें और निम्नलिखित DEALLOCATE .
प्रति सत्र कई तैयार कथनों को प्रबंधित करने के लिए अधिक परिष्कृत एल्गोरिदम संभव हैं, या अतिरिक्त पैरामीटर के रूप में तैयार कथन का नाम लेते हैं, या यहां तक ​​कि नाम के रूप में क्वेरी स्ट्रिंग के MD5 हैश का उपयोग करते हैं, लेकिन यह इससे परे है इस प्रश्न का दायरा।

ध्यान रखें कि PREPARE लेनदेन . के दायरे से बाहर काम करता है , एक बार PREPARE सफल होता है, तैयार कथन सत्र के जीवनकाल के लिए मौजूद होता है। यदि रैपिंग ट्रांजैक्शन निरस्त कर दिया जाता है, तो PREPARE अप्रभावित है। ROLLBACK नहीं तैयार बयानों को हटा दें।

गतिशील क्वेरी निष्पादन

दो क्वेरी, लेकिन केवल एक सर्वर पर कॉल करें। और बहुत कुशल भी।

SELECT f_prep_query('tbl'::regclass, 'pre'::text);
EXECUTE stmt_dyn;

एक अस्थायी तालिका या कर्सर बनाने और उसमें से चयन/प्राप्त करने की तुलना में सबसे सरल उपयोग के मामलों के लिए सरल और अधिक कुशल (जो अन्य विकल्प होंगे)।

एसक्यूएल फिडल.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. यदि मौजूद नहीं है तो PostgreSQL तालिका बनाएं

  2. कैस्केड डिलीट सिर्फ एक बार

  3. SQL क्वेरी के साथ फ़ंक्शन का परिणाम डेटा के लिए कोई गंतव्य नहीं है

  4. डीओ ब्लॉक के अंदर psql मेटा-कमांड द्वारा निर्धारित चर का उपयोग करें

  5. मौजूदा auth.User डेटा को नए Django 1.5 कस्टम उपयोगकर्ता मॉडल में माइग्रेट करना?