上文中我們介紹了DateTime的儲存格式,以及如何使用DateTime;本文主要講述DateTime類型四捨五入的問題。
2. DateTime類型四捨五入問題(rounding issues)
DateTime 與 String 之間的轉換並總是精確的。例如,“20060923 03:23:47:001” 轉換為DateTime類型時,此項將會轉換為離百分之三秒最近的時間。那將會轉換為“20060923 03:23:47.000”。為什麼轉換結果是這樣呢? 是由於資料總是被轉換為 離 3/1000秒為計算單位的最近的時間。那我們是否可以這樣理解這次轉換呢?其實,這次轉換涉及到的結果可以是 .000 和 .003 ,依據離3/1000秒最近的原則,.001 到.000為1毫秒 .001 到.003 是2毫秒,所以結果是.000).上述的字串如果轉換為Smalldatetime類型時,結果將會是"20060923 03:24:00". 轉換為SmallDateTime時,總是將結果轉換為離 分為計算單位最近的時間。可以這樣理解,03:23:47 轉換為SmallDateTime時,可以轉換為 03:23:00 和 03:24:00 由這兩個結果可以知道,轉換字元離03:24:00 只有13秒,所以轉換為 03:24:00.)那如果轉換字元分別為 “03:23:30 ” 和“03:23:29”時,轉換結果是什麼呢?結果為“03:24:00” 和“03:23:00”。
同樣,當String 類型轉換為DateTime時,結果也是不精確的。String類型的值會被轉換為最接近的DateTime類型值。而不會向Decimal類型的值向INT類型的轉換,只是簡單的將後續的小數部分去掉,如10.99轉換結果為10。DateTim資料的毫秒部分總是遵循以下的格式,[0-9][0-9][037]。例如,毫秒部分的值為994時,在轉換為DateTime類型時,最終的結果將會是997. 999將會轉換為下一秒的000。因此,對於如下的語句而言,這就不是一個很好的過濾語句:
Where Dt between '20060211 00:00:00.000' and '20060211 23:59:59.999' .為什麼呢?通過以上分析可知,'20060211 23:59:59.999' 將會轉換為'20060212 00:00:00.000'。 因此根據上述條件,最終的結果中將會包含 '20060212 00:00:00.000' 的資料。為了改進上面的內容,我們可以將上邊界的值改為'20060211 23:59:59.997'。這樣就不會包含 '20060212 00:00:00.000' 的資料了。更好的條件使用方法,如下所示:
Where Dt >= '20060211 00:00:00.000' and Dt<'20060212 00:00:00.000' .這種寫法無論DateTime類型還是SmallDateTime類型,都能夠正常使用。
一些程式員在使用上面的 Dt >= '20060211 00:00:00.000' and Dt<'20060212 00:00:00.000' 時,喜歡去掉時間部分,寫成如下的形式:
Dt >= '20060211' and Dt<'20060212' 在這種形式下,SQL Server 將會將字元形式轉換為指定日期的午夜時間。即 '20060211' 轉換為 20060211 00:00:00.000.
上面的過濾條件是 Search ArgumentSARG),這就意味著查詢最佳化工具會考慮使用索引的查詢操作提高效能。但是有些人會寫成如下的形式,使用SQL Server函數將日期部分取出來,再進行比較,如下:
Where ConvertVarchar(8),dt,112)='20060211' 這種寫法不是SARG形式,資料庫不會使用索引查詢,因此,應當避免此種寫法。
- T-SQL with關鍵字的執行個體應用
- SQL Server 2008下輕鬆調試T-SQL語句
- T-SQL語句建立SQL Server索引
- Microsoft SQL Server 2008技術內幕:T-SQL查詢
- T-SQL編程入門經典(涵蓋SQL Server 2008 & 2005)