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

'तत्काल निष्पादित' करने के लिए गतिशील इनपुट पैरामीटर पास करना

आप 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;]';



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. मैं प्रत्येक उत्पाद के लिए सही आकार का बॉक्स कैसे ढूंढ सकता हूं?

  2. ट्रिगर अगर अन्य

  3. Oracle चर

  4. SQL डेवलपर में बहु-मूल्यवान पैरामीटर के लिए बाइंड कैसे दर्ज करें

  5. Oracle में अस्थायी डेटा के लिए प्रदर्शन विचार