आप using
. के रूप में बाइंड मानों की एक स्ट्रिंग सूची की आपूर्ति नहीं कर सकते पैरामीटर, इसलिए मैं ऐसा करने का एकमात्र तरीका नेस्टेड डायनेमिक SQL कॉल के साथ देख सकता हूं, जो थोड़ा गड़बड़ है, और इसका मतलब है कि आंतरिक में सभी संभावित मापदंडों को घोषित करना (और बांधना)। नेस्टेड, डायनामिक स्टेटमेंट।
declare
v_execute_statement varchar2(4000);
v_flag varchar2(1);
v_start_date date := date '2018-01-01';
v_end_date date := date '2018-01-31';
v_joining_day varchar2(9) := 'MONDAY';
begin
-- loop over all rows for demo
for rec in (
select condition, input_params
From your_table
)
loop
v_execute_statement := q'[
DECLARE
v_start_date date := :v_start_date;
v_end_date date := :v_end_date;
v_joining_day varchar2(9) := :v_joining_day;
BEGIN
EXECUTE IMMEDIATE q'^
BEGIN
IF ]' || rec.condition || q'[ THEN
:o_flag := 'Y';
ELSE
:o_flag := 'N';
END IF;
END;^'
USING ]' || rec.input_params || q'[, OUT :v_flag;
END;]';
dbms_output.put_line('Statement: ' || v_execute_statement);
EXECUTE IMMEDIATE v_execute_statement
USING v_start_date, v_end_date, v_joining_day, OUT v_flag;
dbms_output.put_line('Result flag: ' || v_flag);
end loop;
end;
/
मैंने इस्तेमाल किया है वैकल्पिक उद्धरण तंत्र
बच गए सिंगल कोट्स से भ्रम को कम करने के लिए यहां। उद्धरण के दो नेस्टेड स्तर हैं - बाहरी एक q'[...]'
द्वारा सीमांकित और भीतरी एक q'^...^'
. द्वारा सीमांकित , लेकिन आप अन्य वर्णों का उपयोग कर सकते हैं यदि वे आपकी वास्तविक तालिका सामग्री के कारण समस्या हैं। दो स्तरों के लिए उन उद्धरणों से बचना काफी बदसूरत और कठिन होगा पालन करना/सही होना; और आपको अपनी condition
. में आगे बच निकलने वाले उद्धरणों के बारे में भी चिंता करनी होगी स्ट्रिंग्स, जो आपके द्वारा प्रदान किए गए दूसरे नमूने के लिए आपके मौजूदा कोड के साथ पहले से ही एक समस्या होगी क्योंकि इसमें एक टेक्स्ट शाब्दिक है।
आपकी दो नमूना तालिका पंक्तियों और डमी दिनांक/दिन के मूल्यों के साथ जो मैंने आउटपुट के ऊपर दिखाया है वह है:
Statement:
DECLARE
v_start_date date := :v_start_date;
v_end_date date := :v_end_date;
v_joining_day varchar2(9) := :v_joining_day;
BEGIN
EXECUTE IMMEDIATE q'^
BEGIN
IF :p_end_date < :p_start_date THEN
:o_flag := 'Y';
ELSE
:o_flag := 'N';
END IF;
END;^'
USING v_end_date, IN v_start_date, OUT :o_flag;
END;
Result flag: N
Statement:
DECLARE
v_start_date date := :v_start_date;
v_end_date date := :v_end_date;
v_joining_day varchar2(9) := :v_joining_day;
BEGIN
EXECUTE IMMEDIATE q'^
BEGIN
IF :p_joining_day = 'MONDAY' THEN
:o_flag := 'Y';
ELSE
:o_flag := 'N';
END IF;
END;^'
USING v_joining_day, OUT :o_flag;
END;
Result flag: Y
जनरेट किए गए स्टेटमेंट में ध्यान देने वाली पहली बात डिक्लेयर सेक्शन है, जिसमें input_params
में आपके पास मौजूद सभी संभावित वैरिएबल नामों को सूचीबद्ध करना होगा। , और उन्हें नए बाइंड चर से सेट करें। आपको इन्हें पहले से ही मुख्य ब्लॉक/प्रक्रिया में जानना चाहिए, या तो स्थानीय चर या अधिक संभावित प्रक्रिया तर्क के रूप में; लेकिन उन सभी को यहां डुप्लीकेट किया गया है, क्योंकि इस समय आप नहीं जानते कि किसकी आवश्यकता होगी।
फिर उस कथन का अपना आंतरिक गतिशील SQL है जो अनिवार्य रूप से वही है जो आप मूल रूप से कर रहे थे, लेकिन input_params
में समाप्त हो जाता है स्ट्रिंग और साथ ही condition
।
यहां महत्वपूर्ण हिस्सा उद्धरण है। पहले वाले में, उदाहरण के लिए, दोनों :p_end_date
और :p_start_date
q'^...^'
. के भीतर, उद्धरणों के दूसरे स्तर के अंदर हैं , इसलिए वे स्थानीय v_end_date
के मानों के साथ, आंतरिक गतिशील SQL के लिए बाध्य हैं और v_start_date
उस आंतरिक से execute immediate
।
उस पूरे जेनरेट किए गए ब्लॉक को सभी संभावित परिवर्तनीय नामों के लिए बाध्य मानों के साथ निष्पादित किया जाता है, जो स्थानीय चर के लिए मान प्रदान करता है (v_start_date date := :v_start_date;
के माध्यम से) आदि) डेटा प्रकारों को संरक्षित करते समय; प्लस आउटपुट फ़्लैग.
फिर वह ब्लॉक अपने आंतरिक execute immediate
. को निष्पादित करता है केवल प्रासंगिक स्थानीय चरों का उपयोग करते हुए विवरण, जिसमें अब बाध्य मान हैं; और आउटपुट फ्लैग जो अभी भी बाहरी से एक बाइंड वैरिएबल है execute immediate
, इसलिए बाहरी ब्लॉक अभी भी अपना परिणाम देख सकता है।
आप देख सकते हैं कि दूसरा जेनरेट किया गया स्टेटमेंट एक अलग कंडीशन का उपयोग करता है और वेरिएबल और वैल्यू को पहले से बाइंड करता है, और फ्लैग का मूल्यांकन प्रत्येक केस में प्रासंगिक कंडीशन और पैरामीटर के आधार पर किया जाता है।
संयोग से, आप :o_flag
. के डुप्लीकेट संदर्भ को हटा सकते हैं (जो कोई समस्या नहीं है लेकिन मुझे थोड़ा भ्रमित करने वाला लगता है) इसके बजाय एक केस एक्सप्रेशन का उपयोग करके:
v_execute_statement := q'[
DECLARE
v_start_date date := :v_start_date;
v_end_date date := :v_end_date;
v_joining_day varchar2(9) := :v_joining_day;
BEGIN
EXECUTE IMMEDIATE q'^
BEGIN
:o_flag := CASE WHEN ]' || rec.condition || q'[ THEN 'Y' ELSE 'N' END;
END;^'
USING OUT :v_flag, ]' || rec.input_params || q'[;
END;]';