2013-12-12 6 views
17

में नहीं है क्या CASE और COALESCE() के लिए प्रलेखन में वर्णित शॉर्ट-सर्किट मूल्यांकन SQL में उपयोग किए जाने पर अनुक्रमों पर लागू होता है? ऐसा प्रतीत नहीं होता है।केस और कोलेसे शॉर्ट-सर्किट मूल्यांकन पीएल/एसक्यूएल में अनुक्रमों के साथ काम करता है लेकिन एसक्यूएल

Oracle डाटाबेस शॉर्ट सर्किट मूल्यांकन का उपयोग करता है:

ओरेकल documentation on CASE जो यह बताता है। एक साधारण CASE अभिव्यक्ति के लिए ... यदि पिछली तुलना_एक्सपी expr के बराबर है तो ओरेकल कभी तुलना_expr का मूल्यांकन नहीं करता है। एक खोजी गई CASE अभिव्यक्ति के लिए, डेटाबेस ... पिछली स्थिति सत्य होने पर कभी भी किसी शर्त का मूल्यांकन नहीं करती है।

इसी COALESCE()the documentation कहा गया है कि के लिए:

Oracle डाटाबेस शॉर्ट सर्किट मूल्यांकन का उपयोग करता है। डेटाबेस प्रत्येक एक्सप्रप्रस मान का मूल्यांकन करता है और यह निर्धारित करता है कि उनमें से कोई भी पूर्ण है या नहीं, यह निर्धारित करने से पहले सभी एक्सप्रप्रस मूल्यों का मूल्यांकन करने के बजाय यह शून्य है या नहीं।

एसक्यूएल से अनुक्रम कॉल करते समय यह मामला प्रतीत नहीं होता है; जैसा कि आप देख सकते हैं कि कोई छोटा सर्किट नहीं होता है और अनुक्रम बढ़ता है।

SQL> create sequence tmp_test_seq start with 1 increment by 1; 
SQL> select tmp_test_seq.nextval from dual; 

    NEXTVAL 
---------- 
     1 
SQL> select tmp_test_seq.currval from dual; 

    CURRVAL 
---------- 
     1 
SQL> select coalesce(1, tmp_test_seq.nextval) from dual; 

COALESCE(1,TMP_TEST_SEQ.NEXTVAL) 
-------------------------------- 
           1 
SQL> select tmp_test_seq.currval from dual; 

    CURRVAL 
---------- 
     2 
SQL> select case when 1 = 1 then 1 else tmp_test_seq.nextval end as s from dual; 


     S 
---------- 
     1 
SQL> select tmp_test_seq.currval from dual; 

    CURRVAL 
---------- 
     3 

SQL Fiddle

SQL> create sequence tmp_test_seq start with 1 increment by 1; 
SQL> declare 
    2  i number; 
    3 begin 
    4  i := tmp_test_seq.nextval; 
    5  dbms_output.put_line(tmp_test_seq.currval); 
    6  i := coalesce(1, tmp_test_seq.nextval); 
    7  dbms_output.put_line(i); 
    8  dbms_output.put_line(tmp_test_seq.currval); 
    9  i := case when 1 = 1 then 1 else tmp_test_seq.nextval end; 
10  dbms_output.put_line(i); 
11  dbms_output.put_line(tmp_test_seq.currval); 
12 end; 
13/
1 
1 
1 
1 
1 
SQL> select tmp_test_seq.nextval from dual; 

    NEXTVAL 
---------- 
     2 

PL/SQL से एसक्यूएल में अनुक्रम कॉलिंग एक ही परिणाम के साथ के रूप में एसक्यूएल होता है::

हालांकि, जब PL/SQL से फोन कर अनुक्रम नहीं वृद्धि की जाती है

SQL> create sequence tmp_test_seq start with 1 increment by 1; 
SQL> declare 
    2  i number; 
    3 begin 
    4  select tmp_test_seq.nextval into i from dual; 
    5  dbms_output.put_line(tmp_test_seq.currval); 
    6  select coalesce(1, tmp_test_seq.nextval) into i from dual; 
    7  dbms_output.put_line(i); 
    8  dbms_output.put_line(tmp_test_seq.currval); 
    9  select case when 1 = 1 then 1 else tmp_test_seq.nextval end into i 
10  from dual; 
11  dbms_output.put_line(i); 
12  dbms_output.put_line(tmp_test_seq.currval); 
13 end; 
14/
1 
1 
2 
1 
3 

इस बारे में प्रलेखन में कुछ भी प्रतीत नहीं होता है; the Administrator's guide for managing sequences, the SQL language reference on sequence psuedocolumns, the PL/SQL language reference on CURRVAL and NEXTVAL या the database concepts overview of sequences

क्या एसएसएल में उपयोग किए जाने पर CASE और COALESCE() के शॉर्ट-सर्किट मूल्यांकन अनुक्रमों के लिए होते हैं? क्या यह दस्तावेज है?

यदि हम रुचि रखते हैं तो हम 11.2.0.3.5 पर हैं।

+0

SQL सर्वर में परीक्षण। फ़ंक्शन के लिए अगला VALUE का उपयोग केस, चुनौती, कोल्स, आईआईएफ, इस्नुल और न्यूलिफ़ के भीतर नहीं किया जा सकता है। यह मुझे लगता है कि इससे बचने का एक तरीका है! –

+1

यह मुझे लगता है कि मेटलिंक के लिए एक सवाल है। –

+0

मुझे आश्चर्य होगा अगर किसी ने इससे पहले यह नहीं देखा ... @Alan। मैंने मेटलिंक पर 2331433 खोजने में कामयाब रहा है, जो समान (आईएसएच) दिखता है, लेकिन केवल केस पर और COALESCE नहीं। मुझे ओरेकल की प्रतिक्रिया भी पसंद है, वह सहायक नहीं है। – Ben

उत्तर

4

स्पष्टीकरण कि शॉर्ट-सर्किट मूल्यांकन अनुक्रमों पर क्यों लागू नहीं होता है, निम्न हो सकता है। अनुक्रम क्या है? आंतरिक को अलग रखना, यह अनुक्रम परिभाषा का संयोजन है (seq$ डेटा डिक्शनरी तालिका में रिकॉर्ड) और कुछ आंतरिक एसजीए घटक, यह एक फ़ंक्शन नहीं है और माना जा सकता है, हालांकि प्रलेखन does not state it directly (लेकिन निष्पादन योजना करता है) पंक्ति स्रोत के रूप में। और हर बार जब किसी अनुक्रम को किसी क्वेरी की चयन सूची में सीधे संदर्भित किया जा रहा है, तो इसे ऑप्टिमाइज़र द्वारा मूल्यांकन किया जाना चाहिए जब यह इष्टतम निष्पादन योजना की खोज करता है। एक इष्टतम कार्य योजना लागू करता है, तो nextval pseudocolumn संदर्भित है एक दृश्य की संख्या बढ़ जाता है बनाने की प्रक्रिया के दौरान:

SQL> create sequence seq1; 
Sequence created 

यहाँ हमारे अनुक्रम है:

SQL> select o.obj# 
    2  , o.name 
    3  , s.increment$ 
    4  , s.minvalue 
    5  , s.maxvalue 
    6  , s.cache 
    7 from sys.seq$ s 
    8 join sys.obj$ o 
    9  on (o.obj# = s.obj#) 
10 where o.name = 'SEQ1' 
11 ; 


     OBJ# NAME INCREMENT$ MINVALUE MAXVALUE  CACHE 
---------- ------- ---------- ---------- ---------- ---------- 
    94442 SEQ1    1   1  1E28   20 

क्वेरी के नीचे का पता लगाने की सुविधा देता है, और यह भी पर एक नज़र डालें अपनी कार्य योजना लागू करके

SQL> ALTER SESSION SET EVENTS '10046 trace name context forever, level 4'; 
Session altered 

SQL> select case 
    2   when 1 = 1 then 1 
    3   when 2 = 1 then seq1.nextval 
    4   end as res 
    5 from dual; 

     RES 
---------- 
     1 

/* sequence got incremented by 1 */ 

SQL> select seq1.currval from dual; 

    CURRVAL 
---------- 
     3 

ट्रेस फ़ाइल जानकारी:

STAT # +१०१६१७१५२८ आईडी = 1 cnt = 1 पीआईडी ​​= 0 स्थिति = 1 obj = 94,442 सेशन = 'SEQUENCE SEQ1 ...
STAT # +१०१६१७१५२८ आईडी = 2 cnt = 1 पीआईडी ​​= 1 स्थिति = 1 obj = 0 सेशन = 'फास्ट डुएल ...
बंद # +१०१६१७१५२८: c = 0, ई = 12, डीईपी = 0, type = 0, टिम = 12896600071500/* कर्सर को बंद */

कार्य योजना लागू करके हमें मूलतः एक ही दिखाएगा:

SQL> explain plan for select case 
    2       when 1 = 1 then 1 
    3       else seq1.nextval 
    4       end 
    5      from dual 
    6/
Explained 
Executed in 0 seconds 

SQL> select * from table(dbms_xplan.display()); 
PLAN_TABLE_OUTPUT 
--------------------------------------------------------------- 
Plan hash value: 51561390 
----------------------------------------------------------------- 
| Id | Operation  | Name | Rows | Cost (%CPU)| Time  | 
----------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  2 (0)| 00:00:01 | 
| 1 | SEQUENCE  | SEQ1 |  |   |   | 
| 2 | FAST DUAL  |  |  1 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------- 
9 rows selected 
Executed in 0.172 seconds 

मूल्यांकन के संदर्भ में, एक क्वेरी में सीधे अनुक्रम का संदर्भ, लगभग एक सहसंबंधित उप-क्वेरी सहित। यही कारण है कि सहसंबद्ध उप क्वेरी हमेशा अनुकूलक द्वारा मूल्यांकन किया जाएगा:

SQL> explain plan for select case 
    2       when 1 = 1 then 1 
    3       when 2 = 1 then (select 1 
    4            from dual) 
    5       end as res 
    6      from dual; 
Explained 
Executed in 0 seconds 

SQL> select * from table(dbms_xplan.display()); 
PLAN_TABLE_OUTPUT 
----------------------------------------------------------------- 
Plan hash value: 1317351201 
----------------------------------------------------------------- 
| Id | Operation  | Name | Rows | Cost (%CPU)| Time  | 
----------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  4 (0)| 00:00:01 | 
| 1 | FAST DUAL  |  |  1 |  2 (0)| 00:00:01 | 
| 2 | FAST DUAL  |  |  1 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------- 
9 rows selected 
Executed in 0.063 seconds 

हम देख सकते हैं कि dual तालिका में दो बार निष्पादन योजना में शामिल किया गया है।

उप-क्वेरी के साथ समानता एक भीड़ में बनाई गई थी। निश्चित रूप से समानता की तुलना में अधिक अंतर हैं। अनुक्रम बिल्कुल अलग तंत्र हैं। लेकिन, एक अनुक्रम को ऑप्टिमाइज़र द्वारा पंक्ति स्रोत के रूप में देखा जाता है, और जब तक यह nextval एक अनुक्रम के छद्म प्रोटोकॉल को select शीर्ष-स्तर क्वेरी की सूची में सीधे संदर्भित नहीं किया जाता है, तो यह अनुक्रम का मूल्यांकन नहीं करेगा , अन्यथा अनुक्रम बढ़ाया जाएगा, चाहे शॉर्ट-सर्किट मूल्यांकन तर्क का उपयोग किया जा रहा हो या नहीं। पीएल/एसक्यूएल इंजन, जाहिर है, (ओरेकल 11 जी आर 1 से शुरू) के पास अनुक्रम मूल्य तक पहुंचने का एक अलग तरीका है। ध्यान दिया जाना चाहिए कि आरडीबीएमएस के पिछले 11 जीआर 1 संस्करणों में हमें पीएल/एसक्यूएल ब्लॉक में अनुक्रम को संदर्भित करने के लिए एक प्रश्न लिखना चाहिए, जो पीएल/एसक्यूएल इंजन सीधे एसक्यूएल इंजन को भेजा गया है।

"" का उत्तर ऑप्टिमाइज़र "निष्पादन योजना के दौरान अनुक्रम योजना उत्पन्न करने के दौरान अनुक्रम बढ़ता है, अनुक्रमों के आंतरिक कार्यान्वयन में निहित है।

+0

मुझे लगता है कि शॉर्ट-सर्किट समस्या अनुक्रम से संबंधित नहीं है, जिसका हमेशा चयन विवरण में मूल्यांकन किया जाता है, [ ओरेकल दस्तावेज़ीकरण] (http://docs.oracle.com/cd/E11882_01/server.112/e17118/queries009.htm#SQLRF20036), लेकिन ओरेकल एसक्यूएल इंजन – mucio

+0

के 'केस' और 'कोलेससे' कार्यान्वयन में आपके साथ बदले गए उत्तर में आप वास्तव में संकेत दे रहे हैं कि निकोलस सही है, यह @mucio लगता है, आप इस बात से इंकार कर रहे हैं कि यह एक प्रश्न है ... और यही कारण है कि शॉर्ट सर्किटिंग काम नहीं करती है। – Ben

+0

आपका प्रश्न "क्या एसएएसई और कोलेसेज() का शॉर्ट-सर्किट मूल्यांकन SQL में उपयोग किए जाने पर अनुक्रमों के लिए होता है? क्या यह दस्तावेज है?"निकोलस ने कहा" मूल्यांकन के संदर्भ में, सीधे एक प्रश्न में अनुक्रम का संदर्भ देना, मोटे तौर पर एक सहसंबंधित उप-क्वेरी सहित। "यह सच नहीं है, क्योंकि जहां ... या ... (मेरे डेमो में) उप-क्वेरी के साथ शॉर्ट-सर्किटिंग का उपयोग कर सकते हैं। मेरा सही उत्तर है: ओरेकल का कहना है कि एक चयन में अगली बार हमेशा मूल्यांकन किया जाता है (और केवल एक बार), केस/कोलेसे एक अलग कथन में अलग-अलग व्यवहार करता है (एक साधारण एसक्यूएल में या पीएल में/एसक्यूएल ब्लॉक) पीएल/एसक्यूएल – mucio

5

PL/SQL ओरेकल के लिए भरोसा दिलाते हैं कि यह शॉर्ट सर्किट मूल्यांकन का उपयोग करेगा:

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

से: 2 PL/SQL Language Fundamentals

जब आप SQL कोड में nextval का उपयोग, हम एक अलग स्थिति है।

हम सभी को ध्यान में रखना है कि currval और nextval pseudocolumns हैं सबसे पहले:

एक pseudocolumn एक तालिका स्तंभ की तरह बर्ताव करता है, लेकिन वास्तव तालिका में संग्रहीत नहीं है। आप छद्म कोड से चुन सकते हैं, लेकिन आप अपने मूल्यों को सम्मिलित, अद्यतन या हटा नहीं सकते हैं। बिना छेड़छाड़ के एक फ्यूडोकॉलम भी है (कृपया अध्याय 5, "फ़ंक्शंस" देखें। हालांकि, तर्क के बिना फ़ंक्शन आमतौर पर परिणाम सेट में प्रत्येक पंक्ति के लिए समान मान लौटाते हैं, जबकि छद्म चक्र आमतौर पर एक अलग मूल्य लौटाते हैं प्रत्येक पंक्ति के लिए

से

:। 3 Pseudocolumns

सवाल अब यह है:।? क्यों ओरेकल का मूल्यांकन nextval या इस व्यवहार कहीं कहा गया है

,210

NEXTVAL के लिए एक संदर्भ वाली एकल SQL विवरण के भीतर, ओरेकल एक बार अनुक्रम वृद्धि कर देता है:

  • प्रत्येक पंक्ति एक SELECT कथन के बाहरी क्वेरी ब्लॉक द्वारा वापस लिए। इस तरह के एक प्रश्न ब्लॉक निम्न स्थानों में दिखाई कर सकते हैं:

    1. एक शीर्ष स्तर का चयन करें बयान
    2. एक सम्मिलित करें ... SELECT कथन (या तो एकल मेज या multitable)। एक बहुमूल्य सम्मिलन के लिए, NEXTVAL का संदर्भ VALUES खंड में दिखाई देने वाले को संदर्भित करना चाहिए, और अनुक्रम को के लिए एक बार अद्यतन किया जाता है, जो प्रत्येक पंक्ति को सबक्वायरी द्वारा लौटाया जाता है, भले ही NEXTVAL मल्टीटेबल डालने की कई शाखाओं में संदर्भित हो।
    3. तालिका बनाएं ... के रूप में SELECT कथन
    4. एक दृश्य तैयार करें materialized ... के रूप में SELECT कथन
  • प्रत्येक पंक्ति किसी अद्यतन बयान

  • में अद्यतन प्रत्येक सम्मिलित युक्त बयान के लिए एक VALUES खंड

  • प्रत्येक पंक्ति के लिए एक MERGE कथन द्वारा विलय किया गया। NEXTVAL का संदर्भ merge_insert_clause या merge_update_clause या दोनों में दिखाई दे सकता है। प्रत्येक पंक्ति को अद्यतन करने के लिए NEXTVALUE मान बढ़ाया गया है और प्रत्येक पंक्ति डालने के लिए, भले ही अनुक्रम संख्या वास्तव में अद्यतन या सम्मिलन ऑपरेशन में उपयोग नहीं की जाती है। यदि NEXTVAL को इन स्थानों में से किसी एक में से अधिक निर्दिष्ट किया गया है, तो अनुक्रम को प्रत्येक पंक्ति के लिए एक बार बढ़ाया जाता है और उस पंक्ति को के लिए NEXTVAL की सभी घटनाओं के लिए समान मान देता है।

से: Sequence Pseudocolumns

आपका मामला स्पष्ट रूप से है "1।एक शीर्ष-स्तरीय चयन कथन ", लेकिन इसका मतलब यह नहीं है कि शॉर्ट-सर्किट तर्क नहीं है, लेकिन केवल nextval का मूल्यांकन हमेशा किया जाता है।

यदि आप शॉर्ट-सर्किट तर्क में रुचि रखते हैं, तो यह है बेहतर समीकरण से nextval दूर करने के लिए

इस तरह एक क्वेरी सबक्वेरी का मूल्यांकन नहीं करता है:।

select 6 c 
    from dual 
where 'a' = 'a' or 'a' = (select dummy from dual) 

लेकिन अगर coalesce या case साथ कुछ इसी तरह हम कि Oracle अनुकूलक फैसला देखेंगे करने की कोशिश subqueries निष्पादित करने के लिए:

select 6 c 
    from dual 
where 'a' = coalesce('a', (select dummy from dual)) 

मैंने इसे दिखाने के लिए this demo in SQLFiddle में एनोटेटेड परीक्षण बनाए।

ऐसा लगता है कि ओरेकल शॉर्ट सर्किट तर्क केवल तभी होता है जब ओआरसी के साथ, लेकिन coalesce और case के साथ इसे सभी शाखाओं का मूल्यांकन करना होगा।

मुझे लगता है कि पीएल/एसक्यूएल में आपके पहले परीक्षण से पता चलता है कि coalsce और case ओरेकल राज्यों के रूप में पीएल/एसक्यूएल में शॉर्ट सर्किट तर्क का उपयोग करते हैं। एसक्यूएल कथन में अनुक्रम सहित आपका दूसरा परीक्षण दिखाता है कि उस मामले में nextval का मूल्यांकन किया जाता है, भले ही परिणाम का उपयोग नहीं किया जाता है, और ओरेकल भी दस्तावेज करता है।

दो बातें एक साथ रखें, थोड़ा अजीब लग रहा है क्योंकि coalesce और case व्यवहार वास्तव में असंगत भी मुझे भी लगता है, लेकिन हम ध्यान में रखने के कार्यान्वयन निर्भर (here my source)

है कि उस तर्क के कार्यान्वयन भी है
+1

'मैं ऑप्टिमाइज़र को अगले अनुक्रम का मूल्यांकन न करने के लिए मनाने में सक्षम था' जहां वास्तव में ऐसा हुआ? क्षमा करें यह आपके एसक्यूएल पहेली में नहीं मिल सका। –

+0

अंतिम क्वेरी एक त्रुटि लौटाती है (ओआरए -02287: अनुक्रम संख्या यहां अनुमति नहीं है), भले ही एक संख्यात्मक मानों की अनुमति है (क्वेरी से पहले 'CHR (64 +1) ') का उपयोग करता है। तो मेरी व्याख्या, लेकिन मुझे यह जानकर प्रसन्नता होगी कि एक बेहतर तरीका है, यह है कि आखिरी पूछताछ के लिए अनुकूलक व्यवहार अलग है। 'अगलीवाल' का मूल्यांकन नहीं किया गया है, लेकिन यह ओरेकल को क्वेरी संकलित करने की अनुमति नहीं देता है। जैसा कि आप देख सकते हैं कि मैंने 'अगलीवाल 'को' डुएल से चुनें '(दूसरी क्वेरी) और' कोलेसेई 'और' सीएचआर '(चौथी क्वेरी) में समस्याओं के बिना इस्तेमाल किया, इसलिए मैंने निष्कर्ष निकाला कि समस्या, एक सबक्वायरी के अंदर,' अगलीवाल 'का मूल्यांकन नहीं किया गया है – mucio

+1

दुर्भाग्यवश इसका शॉर्ट सर्किट मूल्यांकन के साथ कुछ लेना देना नहीं है। अंतिम क्वेरी उस त्रुटि को वापस लौटाती है क्योंकि इसे उप-क्वेरी में अनुक्रमों का उपयोग करने की अनुमति नहीं है, और [दस्तावेज़ इसे बताता है] (http://docs.oracle.com/cd/B28359_01/server.111/b28310/views002.htm # ADMIN11800) बहुत स्पष्ट रूप से। –

संबंधित मुद्दे