2012-12-04 8 views
16

यह सरल केस अभिव्यक्ति की तरह लगता है और DECODE फ़ंक्शन समकक्ष हैं और उनके द्वारा लौटाए गए परिणाम समान होना चाहिए। क्या वो?क्या कोई केस स्टेटमेंट और डेकोडे समतुल्य है?

सरल मामला अभिव्यक्ति जिसके लिए selector_value चयनकर्ता से मेल खाता पहले परिणाम देता है:

प्रलेखन निम्नलिखित simple CASE expression के बारे में क्या कहना है। शेष अभिव्यक्ति मूल्यांकन नहीं हैं। यदि कोई selector_value मिलान चयनकर्ता नहीं है, तो CASE अभिव्यक्ति यदि मौजूद है और अन्यथा अन्यथा वापस लौटाता है।

इसे DECODE function से तुलना करना, विवरण समान दिखते हैं।

DECODE प्रत्येक खोज मूल्य को एक-एक करके तुलना करता है। यदि expr एक खोज के लिए बराबर है, तो ओरेकल डेटाबेस इसी परिणाम को देता है। यदि कोई मिलान नहीं मिला है, तो ओरेकल डिफ़ॉल्ट लौटाता है। यदि डिफ़ॉल्ट छोड़ा जाता है, तो ओरेकल वापस शून्य देता है।

searched CASE expression सरल के बराबर हो सकता है, यह भी वही माना जा सकता है।

इन तीन बयानों सभी एक ही परिणाम वापस जाने के लिए लगता है, 0.

select case 1 when 2 then null else 0 end as simple_case 
    , case when 1 = 2 then null else 0 end as searched_case 
    , decode(1, 2, null, 0) as decode 
    from dual 

सरल मामला अभिव्यक्ति और डीकोड करने समारोह (और विशिष्ट परिस्थितियों में खोजा गया मामला अभिव्यक्ति) हमेशा एक ही परिणाम लौट रहा है?

उत्तर

13

बेन डीकोड करने और मामले के बीच मतभेदों पर एक लंबा जवाब लिखा है की तुलना करने के लिए नहीं किया जा सकता है। वह दर्शाता है कि डेकोडे और सीएएसई स्पष्ट रूप से समझाते हुए मूल्यों के समान सेट के लिए अलग-अलग डेटाटाइप वापस कर सकते हैं क्यों ऐसा होता है।

डेकोडे() काफी अनुवादात्मक है: यह हमेशा पहले परिणाम पैरामीटर का डेटाटाइप है। ओरेकल सभी अन्य परिणाम मानकों पर अंतर्निहित रूपांतरण लागू करता है। यह एक त्रुटि फेंक देगा, अगर (कहें) पहला परिणाम पैरामीटर संख्यात्मक है और डिफ़ॉल्ट मान एक तिथि है।

ORA-00932: inconsistent datatypes: expected NUMBER got DATE 

यह दस्तावेज़ीकरण में वर्णित है: find out more

पहले परिदृश्य में पहला परिणाम पैरामीटर न्यूल है, जो ओरेकल VARCHAR2 के रूप में व्यवहार करने का निर्णय लेता है। यदि हम इसे बदलते हैं तो पहला परिणाम पैरामीटर संख्यात्मक है और डिफ़ॉल्ट मान शून्य है DECODE() कथन एक NUMBER वापस करेगा; एक डंप() साबित करता है कि ऐसा है।

जबकि सीएएसई जोर देकर कहते हैं कि सभी लौटे हुए मूल्यों में एक ही डेटाटाइप होता है, और यदि यह मामला नहीं है तो संकलन त्रुटि फेंक देगा। यह निहित रूपांतरण लागू नहीं करेगा। यह दस्तावेज में भी शामिल है। Read it here

अंतर इस पर उबाल जाता है। निम्नलिखित डीकोड करने बयान चलाया जाएगा, मामला बयान नहीं करेंगे:

select decode(1, 1, 1, '1') from dual; 

select case 1 when 1 then 1 else '1' end from dual; 

Obligatory SQL Fiddle.

+4

आप सही हैं यह बहुत आसान है :-)। – Ben

+0

SO पर उत्तर के संबंध में अक्सर कम होता है। – user2672165

24

संक्षिप्त उत्तर, नहीं।

थोड़ा लंबा जवाब लगभग है।

यह केवल दिखाई देता है कि प्रत्येक कथन से प्राप्त परिणाम समान है। अगर हम डेटा प्रकार का मूल्यांकन करने के DUMP फ़ंक्शन का उपयोग लौटे आप देखेंगे कि मैं क्या मतलब है:

SQL> select dump(case 1 when 2 then null else 0 end) as simple_case 
    2  , dump(case when 1 = 2 then null else 0 end) as searched_case 
    3  , dump(decode(1, 2, null, 0)) as decode 
    4 from dual; 

SIMPLE_CASE  SEARCHED_CASE  DECODE 
------------------ ------------------ ----------------- 
Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=1 Len=1: 48 

SQL Fiddle

आप देख सकते हैं कि डीकोड करने के डेटा प्रकार 1 है, जबकि दो मामले बयान "डेटा" का डेटा प्रकार 2. ओरेकल के Data Type Summary का उपयोग करके, DECODE एक VARCHAR2 (डेटा प्रकार 1) लौटा रहा है जबकि CASE कथन "वापसी" संख्याएं (डेटा प्रकार 2) हैं।

मुझे लगता है कि ऐसा इसलिए होता है, क्योंकि नाम बताते हैं कि DECODE फ़ंक्शन है और CASE नहीं है, जिसका अर्थ है कि उन्हें आंतरिक रूप से अलग-अलग कार्यान्वित किया गया है। इसे साबित करने का कोई वास्तविक तरीका नहीं है।

आपको लगता है कि यह वास्तव में कुछ भी प्रभावित नहीं करता है। यदि आपको इसकी संख्या ओरेकल होने की आवश्यकता है तो यह वर्ण को implicit conversion rules के तहत एक संख्या में रूपांतरित कर देगा, है ना? यह या तो सत्य नहीं है, यह won't work in a UNION डेटा प्रकार के समान होने के लिए है; आपके लिए चीजों को आसान बनाने के लिए ओरेकल कोई अंतर्निहित रूपांतरण नहीं करेगा।

ओरेकल अनुशंसा करता है कि स्पष्ट रूपांतरण निर्दिष्ट करते हैं, बजाय अस्पष्ट या स्वत: रूपांतरण पर भरोसा करते हैं, इन कारणों से::

  • SQL कथन को समझने के लिए आसान होता है दूसरे, यहां ओरेकल अंतर्निहित रूपांतरण के बारे में क्या कहते हैं है जब आप स्पष्ट डेटा प्रकार रूपांतरण कार्यों का उपयोग करते हैं।

  • लागू डेटा प्रकार रूपांतरण प्रदर्शन पर नकारात्मक प्रभाव डाल सकता है, विशेष रूप से यदि कॉलम मान का डेटा प्रकार किसी अन्य तरीके से स्थिर की तरह परिवर्तित हो जाता है।

  • लागू रूपांतरण उस संदर्भ पर निर्भर करता है जिसमें यह होता है और हर मामले में एक ही तरीके से काम नहीं कर सकता है। उदाहरण के लिए, किसी डेटाटाइम मान से VARCHAR2 मान में अंतर्निहित रूपांतरण NLS_DATE_FORMAT पैरामीटर के मान के आधार पर एक अप्रत्याशित वर्ष लौटा सकता है।

  • निहित रूपांतरण के लिए एल्गोरिदम सॉफ़्टवेयर रिलीज़ और ओरेकल उत्पादों में परिवर्तन के अधीन हैं। स्पष्ट रूपांतरणों का व्यवहार अधिक अनुमानित है।

एक सुंदर सूची नहीं है यही कारण है कि; लेकिन अंतिम बिंदु मुझे तारीखों पर अच्छी तरह से लाता है। हम पहले की क्वेरी लेने के लिए और यह एक के बजाय एक तिथि का उपयोग करता है में तब्दील हैं:

select case sysdate when trunc(sysdate) then null 
        else sysdate 
     end as simple_case 
    , case when sysdate = trunc(sysdate) then null 
      else sysdate 
     end as searched_case 
    , decode(sysdate, trunc(sysdate), null, sysdate) as decode 
    from dual; 

एक बार फिर, इस प्रश्न पर DUMP का उपयोग कर मामले बयान डेटा प्रकार 12, एक दिन तक का प्रतिफल। DECODE ने sysdate को VARCHAR2 में परिवर्तित कर दिया है।

SQL> select dump(case sysdate when trunc(sysdate) then null 
    2       else sysdate 
    3    end) as simple_case 
    4  , dump(case when sysdate = trunc(sysdate) then null 
    5     else sysdate 
    6    end) as searched_case 
    7  , dump(decode(sysdate, trunc(sysdate), null, sysdate)) as decode 
    8 from dual; 

SIMPLE_CASE   
---------------------------------- 
Typ=12 Len=7: 120,112,12,4,22,18,7 
SEARCHED_CASE 
---------------------------------- 
Typ=12 Len=7: 120,112,12,4,22,18,7 
DECODE 
---------------------------------- 
Typ=1 Len=19: 50,48,49,50,45,49,50,45,48,52,32,50,49,58,49,55,58,48,54 

SQL Fiddle

नोट (एसक्यूएल फिडल में) DATE के सत्र NLS_DATE_FORMAT का उपयोग कर एक चरित्र में बदल दिया गया।

एक तिथि जो पूर्ण रूप से VARCHAR2 में परिवर्तित हो गई है, समस्याएं पैदा कर सकती है। यदि आप अपनी तिथि को किसी चरित्र में बदलने के लिए TO_CHAR का उपयोग करना चाहते हैं, तो आपकी क्वेरी उस ब्रेक को तोड़ देगी जहां आप इसकी अपेक्षा नहीं कर रहे हैं।

SQL> select to_char(decode(sysdate 
    2       , trunc(sysdate), null 
    3       , sysdate) 
    4     , 'yyyy-mm-dd') as to_char 
    5 from dual; 
select to_char(decode(sysdate 
       * 
ERROR at line 1: 
ORA-01722: invalid number 

SQL Fiddle

समान रूप से, तिथि अंकगणित नहीं रह गया काम करता है:

SQL> 
SQL> 
SQL> select decode(sysdate, trunc(sysdate), null, sysdate) + 1 as decode 
    2 from dual; 
select decode(sysdate, trunc(sysdate), null, sysdate) + 1 as decode 
     * 
ERROR at line 1: 
ORA-01722: invalid number 

SQL Fiddle

दिलचस्प बात यह है केवल डिकोड एक VARCHAR2 को अभिव्यक्ति धर्मान्तरित यदि संभव हो तो परिणामों में से एक शून्य है। यदि डिफ़ॉल्ट मान शून्य है तो ऐसा नहीं होता है। उदाहरण के लिए:

SQL> select decode(sysdate, sysdate, sysdate, null) as decode 
    2 from dual; 

DECODE 
------------------- 
2012-12-04 21:18:32 

SQL> select dump(decode(sysdate, sysdate, sysdate, null)) as decode 
    2 from dual; 

DECODE 
------------------------------------------  
Typ=13 Len=8: 220,7,12,4,21,18,32,0 

SQL Fiddle

ध्यान दें कि डीकोड करने 13. यह दस्तावेज नहीं है, लेकिन है की एक डेटा प्रकार वापस आ गया है, मुझे लगता है, आदि काम करता है तारीख गणित के रूप में की तारीख का एक प्रकार है।

संक्षेप में, यदि आप संभवतः DECODE से बचें; आपको जरूरी डेटा प्रकारों की आवश्यकता नहीं हो सकती है जो आप उम्मीद कर रहे हैं। quote Tom Kyte:

डीकोड कुछ हद तक अस्पष्ट है - केस बहुत स्पष्ट है। चीजें जो डीकोड में करना आसान है केस में करना आसान है, हार्ड या डीकोड के साथ असंभव के पास असंभव चीजें केस में करना आसान है। केस, तर्क बुद्धिमान, हाथ नीचे जीतता है।


बस पूरा होने के लिए वहाँ डीकोड करने और मामले के बीच दो कार्यात्मक मतभेद हैं।

  1. DECODE पीएल/एसक्यूएल के भीतर उपयोग नहीं किया जा सकता है।
  2. मामला nulls सीधे

    SQL> select case null when null then null else 1 end as case1 
        2  , case when null is null then null else 1 end as case2 
        3  , decode(null, null, null, 1) as decode 
        4 from dual 
        5   ; 
    
        CASE1  CASE2 DECODE 
    ---------- ---------- ------ 
         1 
    

    SQL Fiddle

+1

+1 और मैं चाहता हूँ मैं कर सकता +5 - अब मैं एक व्यापक उत्तर कहता हूं। –

+0

आपको बहुत धन्यवाद @ जस्टिन, आप से उच्च प्रशंसा! मैं इस बारे में एक महीने के लिए सोच रहा था क्योंकि मैं बुरी तरह पकड़ा गया था इसलिए मेरे पास लिखने के लिए पर्याप्त समय था :-)। – Ben

+0

मेरे साथ +1 भी। मैंने शपथ ली होगी कि वे समान हैं (हालांकि मैं टॉम क्यटे के समान कारणों से केस पसंद करता हूं)। –

-3

मैं जानता हूँ कि मैं बहुत देर हो चुकी है लेकिन यहाँ पोस्टिंग क्योंकि अगर उस के लिए कोई खोज उम्मीद है कि यह मदद कर सकता है कर रहा हूँ। मैं वही

Declare @Var varchar(399)='DECODE(MyColumnName,''A'',''Auto'',''M'',''Manual'')' 

Begin 
Declare @Count int, @Counter int=1 
Declare @TempTable table (ID int identity(1,1),Items varchar(500)) 
Declare @SqlText varchar(max) 
Select @Var=Replace(Replace(@Var,'DECODE(',''),')','') 

Insert Into @TempTable 
Select * FROM [dbo].[Split] (@Var ,',') 
--Select * from @TempTable 
Select @Count=Count(ID) from @TempTable 

While(@Counter<[email protected]) 
Begin 
    If(@Counter=1) 
    Begin 
    Select @SqlText='Case ' +Items from @TempTable Where ID=1 
    End 

    Else If(@[email protected]) 
    Begin 
    Select @SqlText+=' Then ' +Items +' End' from @TempTable Where [email protected] 
    End 

    Else If(@Counter%2=0) 
    Begin 
    Select @SqlText +=' When ' +Items from @TempTable Where [email protected] 
    End 

    Else If(@Counter%2=1) 
    Begin 
    Select @SqlText +=' Then ' +Items from @TempTable Where [email protected] 
    End 

    Set @Counter+=1 
End 

Select @SqlText SqlServerCaseStatement 
End 

के लिए एक MSSQL स्क्रिप्ट बनाया है मैं, ऊपर स्क्रिप्ट में विभाजित करें फ़ंक्शन का इस्तेमाल किया है, तो आपको लगता है कि समारोह की जरूरत है आप Romil के जवाब उल्लेख कर सकते हैं - How to split a comma-separated value to columns

+0

हाय, धन्यवाद, लेकिन मुझे लगता है कि आप पूरी तरह से प्रश्न के बिंदु को याद कर चुके हैं ... और यह ओरेकल के लिए SQL सर्वर नहीं है ... – Ben

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