2010-01-12 13 views
8

में गलत परिणाम देता है मैं SQL सर्वर 2005 में डेटाटाइम फ़ील्ड का उपयोग करके एक अजीब बग में चल रहा हूं। डेटाटाइम फ़ील्ड मिलीसेकंड-स्तर सटीकता के साथ दिखाई देता है, लेकिन ऐसा लगता है कि मिलीसेकंड नहीं हैं हमेशा इस्तेमाल किया।मिलीसेकंड के साथ डेटाटाइम फ़ील्ड पर क्वेरी SQL सर्वर

SELECT col1, YEAR(col1) AS yr, MONTH(col1) AS mn, DAY(col1) AS dy 
FROM mytable 
WHERE col1 >= '2009-12-31 00:00:00.0' AND col1 <= '2009-12-31 23:59:59.999' 
ORDER BY col1 

मेरे परिणाम में मैं मिलता है:: यहाँ अपने परीक्षण क्वेरी है

 
col1      | yr | mn | dy 
----------------------------+------+----+---- 
2009-12-31 00:00:00:00.000 | 2009 | 12 | 31 
2010-01-01 00:00:00:00.000 | 2010 | 1 | 1 

समस्या यह है कि मैं 2010-01-01 तारीख मिल गया है, भले ही उस से कम या बराबर नहीं होना चाहिए "200 9-12-31 23: 5 9: 5 9.9 99"। लेकिन अगर मैं "2009-12-31 23: 59: 59.99 " का उपयोग करने के लिए क्वेरी बदलता हूं, तो यह ठीक काम करता है (2010 की तारीखें वापस नहीं आती हैं)।

क्या यह एक बग है, या यह है कि SQL सर्वर कैसे काम करता है? यदि यह इस तरह काम करता है, तो इसके लिए कोई कारण है? मैं माइस्क्लुएल से कुछ प्रश्नों को माइग्रेट करने में भाग गया, जहां यह अपेक्षित काम करता है (भले ही MySQL मिलीसेकंड भी स्टोर नहीं करता है!)।

उत्तर

12

SQL Server मध्यरात्रि से 1/300 दूसरी लंबी टिकों की संख्या के रूप में समय भाग स्टोर करता है।

23:59:59.999 अगले दिन के 00:00:00.000 होने के निकटतम टिक में घूमता है।

SELECT CAST(CAST('2009-12-01 00:00:00.000' AS DATETIME) AS BINARY(8)), 
     CAST(CAST('2009-12-01 23:59:59.997' AS DATETIME) AS BINARY(8)), 
     CAST(CAST('2009-12-01 23:59:59.999' AS DATETIME) AS BINARY(8)) 



0x00009B8F 00000000 0x00009B8F 018B81FF 0x00009B90 00000000 

पहले मूल्य में, तिथि हिस्सा है, 0x9B8F (39823) Jan 1st, 1900 के बाद से दिनों की संख्या है, और समय हिस्सा है, 0 है, आधी रात के बाद से टिक की संख्या है।

दूसरे मूल्य में, 0x018B81FF (25919999, या 24 * 60 * 60 * 300 - 1) मध्यरात्रि से अधिकतम संभव संख्या में टिक है।

अंत में, तीसरे मान के समय में 0 है और तिथि भाग में वृद्धि हुई है।

+2

की एक विशेष संस्करण यह आपके कोड, उपयोग में एक विकल्प है, तो क्या करना चाहिए है इससे कम: "... और col1 <'2010-1-1 00: 00: 00.0' –

+4

बस संदर्भ जोड़ने के लिए: http://msdn.microsoft.com/en-us/library/ms187819.aspx 'शुद्धता: .000, .003, या .007 सेकेंड ' –

+0

3.33-मिलीसेकंद टिकों की वृद्धि के लिए बढ़ा। मुझे आश्चर्य है कि पृथ्वी पर उन्होंने क्यों चुना? अगर वे इसे 32-बिट दिनांक और 32-बिट समय के रूप में संग्रहीत कर रहे हैं, एक दिन में मिलीसेकंड की कुल संख्या केवल 0x05265c00 है, जो कमरे के साथ 32-बिट पूर्णांक में फिट बैठती है। – Jenni

2

यह एक बग नहीं है। यह पूरी तरह से अपेक्षित व्यवहार है। यहाँ देखो: datetime and smalldatetime

आप इसे

WHERE col1 >= '2009-12-31 00:00:00.0' AND col1 < '2010-01-01' 
1
सभी बिंदु प्रकार चल साथ

में बदल जानी चाहिए, और दिनांक/समय वास्तव में चल बिन्दु मूल्य की तरह है, तो आप उस तरह समानता तुलना से बचने के लिए प्रयास करना चाहिए ।

तो बजाय:

WHERE x <= 10.999 

आपको क्या करना चाहिए:

WHERE x < 11 

तो बजाय का अंतिम मान आप शामिल करना चाहते प्रविष्टि, आपको पहले मूल्य आपके द्वारा बहिष्कृत करना चाहते हैं, आम तौर पर इस काम करता है सूची बेहतर जब सीमाएं पूरी संख्या होती हैं, क्योंकि उनके पास प्रकार के डोमेन में सटीक रूप से प्रतिनिधित्व करने का एक बड़ा मौका होता है।

WHERE ... col1 < '2010-01-01 00:00:00.000' 
      ^
       |    ^-- changed to 2010 
       ^-- changed <= to < 
1

और इसी कारण 'के बीच' तुलना ऑपरेटर दिनांकों लिए अनुशंसित नहीं है है:

अपने विशेष मामले में, मैं यह करने के लिए बदल जाएगा। 'बीच' एक समावेशी तुलना (मूल्यों से मेल खाने वाले दोनों सिरों शामिल किए गए हैं) और इसके बाद के संस्करण की सिफारिश की है, तो आप bottomvalue < testvalue topvalue

जैसे के बीच <
संबंधित मुद्दे