2013-08-29 8 views
8

पहले, मुझे पता है कि यह प्रश्न आम तौर पर Equals(=) vs. LIKE पोस्ट किया गया है।बराबर (=) बनाम दिनांक डेटा प्रकार

SELECT ACCOUNT.ACCOUNT_ID, ACCOUNT.LAST_TRANSACTION_DATE 
FROM ACCOUNT 
WHERE ACCOUNT.LAST_TRANSACTION_DATE LIKE '30-JUL-07'; 

मैं सभी पंक्तियों मैं तलाश कर रहा हूँ हो: यहाँ, मैं Oracle डाटाबेस पर दिनांक प्रकार डेटा के बारे में क्वेरी, मैं जब मैं इस तरह से चयन बयान लिखते हैं, निम्नलिखित पाया। लेकिन जब मैं प्रवेश का उपयोग करते बराबर = बजाय:

SELECT ACCOUNT.ACCOUNT_ID, ACCOUNT.LAST_TRANSACTION_DATE 
FROM ACCOUNT 
WHERE ACCOUNT.LAST_TRANSACTION_DATE = '30-JUL-07'; 

मैं कुछ भी नहीं है, भले ही कुछ भी नहीं बराबर के चिह्न को छोड़कर अलग है मिलता है। क्या मुझे इसके लिए कोई स्पष्टीकरण मिल सकता है?

+1

मुझे लगता है कि पहला व्यक्ति केवल 30-जुलाई -07 00: 00: 00' से मेल खाता है जबकि दूसरे मैच '30-Jul-07 **: **: **'? –

उत्तर

14

LAST_TRANSACTION_DATE मान लिया जाये कि एक DATE स्तंभ (या TIMESTAMP) तो दोनों संस्करण बहुत बुरा व्यवहार कर रहे हैं।

दोनों मामलों में DATE कॉलम वर्तमान एनएलएस सेटिंग्स के आधार पर निश्चित रूप से एक वर्ण शाब्दिक में परिवर्तित हो जाएगा।इसका मतलब है कि विभिन्न ग्राहकों के साथ आपको अलग-अलग परिणाम मिलेंगे।

तारीख शाब्दिक (!) एक प्रारूप मुखौटा के साथ हमेशा उपयोग to_date() या एक एएनएसआई तारीख शाब्दिक का उपयोग का उपयोग करते समय। इस तरह आप तिथियों की तारीखों की तुलना तारों के साथ तारों की तुलना नहीं करते हैं। तो बराबर की तुलना के लिए आप का उपयोग करना चाहिए:

LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy') 

ध्यान दें कि 'सोम' का उपयोग अभी भी विभिन्न NLS सेटिंग्स ('DEC' बनाम 'DEZ' या 'MAR' बनाम 'MRZ') के साथ त्रुटियों के लिए नेतृत्व कर सकते हैं।

LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy') 

या एक एएनएसआई तारीख शाब्दिक

LAST_TRANSACTION_DATE = DATE '2007-07-30' 

अब कारण है कि इसके बाद के संस्करण क्वेरी बहुत वापस जाने के लिए कुछ भी नहीं है की संभावना है का उपयोग करते हुए: यह बहुत त्रुटियों की संभावना कम महीने नंबर का उपयोग कर (और चार अंकों वर्ष) है कि ओरेकल DATE कॉलम में समय भी शामिल है। उपर्युक्त दिनांक शाब्दिक रूप से समय 00:00 शामिल है। यदि तालिका में समय अलग है (उदा। 19:54) तो निश्चित रूप से तिथियां बराबर नहीं हैं।

इस समस्या को वैकल्पिक हल के लिए आप अलग अलग विकल्प हैं: तालिका स्तंभ पर

  1. उपयोग trunc()00:00 trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 इस के लिए समय "सामान्य" लेकिन LAST_TRANSACTION_DATE
  2. पर परिभाषित एक सूचकांक के उपयोग नहीं कर पाएगा का उपयोग
  3. between
    LAST_TRANSACTION_DATE between to_date('2007-07-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and to_date('2007-07-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss')

पहले समाधान की प्रदर्शन समस्या को trunc(LAST_TRANSACTION_DATE) पर एक इंडेक्स बनाकर काम किया जा सकता है जिसका उपयोग उस अभिव्यक्ति द्वारा किया जा सकता है। लेकिन अभिव्यक्ति LAST_TRANSACTION_DATE = '30-JUL-07' रूप में अच्छी तरह क्योंकि आंतरिक रूप से यह के रूप में to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'

संसाधित एक सूचकांक के उपयोग से बचाता है महत्वपूर्ण बातें याद करने के लिए:

  1. कभी नहीं, कभी अंतर्निहित डेटा प्रकार रूपांतरण पर निर्भर हैं। यह आपको किसी बिंदु पर समस्याएं देगा। हमेशा सही डेटा प्रकारों की तुलना करें
  2. ओरेकल DATE कॉलम में हमेशा एक ऐसा समय होता है जो तुलना नियमों का हिस्सा होता है।
+0

LAST_TRANSACTION_DATE = to_date ('30 -07-2007 ',' dd-mm-yyyyy ') पर एक अतिरिक्त' y 'है, कृपया संपादित करें। मैं खुद से संपादित नहीं कर सकता क्योंकि मुझे कम से कम 6 अक्षर संपादित करने की आवश्यकता है :) धन्यवाद –

+1

@QHero: धन्यवाद, सही –

1

दिनांक फ़ील्ड एक स्ट्रिंग नहीं है। जब आप = का उपयोग करते हैं, तो आंतरिक रूप से एक अंतर्निहित रूपांतरण स्ट्रिंग में किया जाता है, जो कुछ भी मेल नहीं खाता है क्योंकि आपकी स्ट्रिंग में आवश्यक मात्रा में सटीकता नहीं है।

मुझे लगता है कि LIKE कथन एक तिथि क्षेत्र के साथ कुछ अलग तरीके से व्यवहार करता है, जिसके कारण तुलनात्मक रूप से जंगलीकार्ड का उपयोग किसी भी परिशुद्धता के लिए आवश्यकता को समाप्त करता है। अनिवार्य रूप से, इस तरह से अपनी LIKE काम करता है:

SELECT ACCOUNT.ACCOUNT_ID, ACCOUNT.LAST_TRANSACTION_DATE 
FROM ACCOUNT 
WHERE ACCOUNT.LAST_TRANSACTION_DATE BETWEEN DATE('30-JUL-07 00:00:00.00000+00:00') AND DATE('30-JUL-07 23:59:59.99999+00:00'); 
6

आप एक तारीख एक स्ट्रिंग के लिए सीधे तुलना नहीं करना चाहिए। आप implicit conversions पर भरोसा करते हैं, जिनके नियम याद रखना मुश्किल है।

इसके अलावा, आपकी तिथि प्रारूप का विकल्प इष्टतम नहीं है: वर्षों में चार अंक (वाई 2 के बग?) हैं, और सभी भाषाओं में JUL नामक वर्ष का सातवां महीना नहीं है। आपको YYYY/MM/DD जैसे कुछ का उपयोग करना चाहिए।

अंत में, ओरेकल में तिथियां समय के सटीक समय के बिंदु हैं। सभी तिथियों में समय घटक है, भले ही यह 00:00:00 है। जब आप = ऑपरेटर का उपयोग करते हैं, तो ओरेकल तिथियों के लिए दिनांक और समय की तुलना करेगा।

SQL> create table test_date (d date); 

Table created 

SQL> alter session set nls_date_format = 'DD-MON-RR'; 

Session altered 

SQL> insert into test_date values 
    2  (to_date ('2007/07/30 11:50:00', 'yyyy/mm/dd hh24:mi:ss')); 

1 row inserted 

SQL> select * from test_date where d = '30-JUL-07'; 

D 
----------- 

SQL> select * from test_date where d like '30-JUL-07'; 

D 
----------- 
30/07/2007 

आप = ऑपरेटर का उपयोग करते, ओरेकल निरंतर स्ट्रिंग 30-JUL-07 एक तारीख को, इस तरह बदलने और स्तंभ के साथ मूल्य की तुलना करेंगे:

यहाँ एक परीक्षण का मामला व्यवहार आप वर्णित के पुनरुत्पादन है

SQL> select * from test_date where d = to_date('30-JUL-07', 'DD-MON-RR'); 

D 
----------- 

आप LIKE ऑपरेटर का उपयोग करते, ओरेकल एक स्ट्रिंग के लिए स्तंभ बदलने और दाएँ हाथ की ओर है, जो के बराबर है की तुलना देगा:

SQL> select * from test_date where to_char(d, 'DD-MON-RR') like '30-JUL-07'; 

D 
----------- 
30/07/2007 

हमेशा तारीखों और तारों के तारों की तिथियों की तुलना करें। संबंधित प्रश्न:

+0

मानते हैं कि इन डेटा प्रारूपों को मेरे नियंत्रण में नहीं है और मुझे 30-JUL-07 की तारीख से तुलना करने की आवश्यकता है, मुझे लगता है कि मुझे इस तरह के स्पष्ट रूपांतरण का उपयोग करना है जैसे'_ -30 -JUL-07 ')। सही? – Hawk

+4

आपको दो तर्कों के साथ 'to_date' का उपयोग करना होगा (निरंतर ** और ** प्रारूप :)। इसके अलावा 'LIKE' कड़ाई से एक स्ट्रिंग ऑपरेटर है और क्योंकि यह तिथियों के साथ अच्छी तरह से काम नहीं करेगा। –

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