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;
एक अस्थायी तालिका या कर्सर बनाने और उसमें से चयन/प्राप्त करने की तुलना में सबसे सरल उपयोग के मामलों के लिए सरल और अधिक कुशल (जो अन्य विकल्प होंगे)।
एसक्यूएल फिडल.