DATETIME データ型のミリ秒に関する注意事項

 

神谷 雅紀
SQL Server Escalation Engineer

 

以下を実行した場合、最後の SELECT はどのような結果を返すでしょうか?

 

use tempdb
go
create table t (n int, d datetime)
go
insert into t values (0,'2013/5/1 23:59:59.990')
insert into t values (1,'2013/5/1 23:59:59.991')
insert into t values (2,'2013/5/1 23:59:59.992')
insert into t values (3,'2013/5/1 23:59:59.993')
insert into t values (4,'2013/5/1 23:59:59.994')
insert into t values (5,'2013/5/1 23:59:59.995')
insert into t values (6,'2013/5/1 23:59:59.996')
insert into t values (7,'2013/5/1 23:59:59.997')
insert into t values (8,'2013/5/1 23:59:59.998')
insert into t values (9,'2013/5/1 23:59:59.999')
insert into t values (10,'2013/5/2 00:00:00.000')
go
select * from t where d = '2013/5/1 23:59:59.999'
go

 

正解は以下です。

 

n d
----------- -----------------------
9 2013-05-02 00:00:00.000
10 2013-05-02 00:00:00.000

 

結果はクエリの検索条件 '2013/5/1 23:59:59.999' に一致しませんし、2 行返されています。なぜでしょう?

 

これは、datetime データ型の時刻範囲が 00:00:00 ~ 23:59:59.997 であり、ミリ秒の精度が .000、.003、.007 であるためです。
.000、.003、.007 以外の値は .000、.003、.007 に丸められます。

 

上の例のテーブルに格納されているデータを見てみると、以下のようになっています。

 

n d
----------- -----------------------
0 2013-05-01 23:59:59.990
1 2013-05-01 23:59:59.990
2 2013-05-01 23:59:59.993
3 2013-05-01 23:59:59.993
4 2013-05-01 23:59:59.993
5 2013-05-01 23:59:59.997
6 2013-05-01 23:59:59.997
7 2013-05-01 23:59:59.997
8 2013-05-01 23:59:59.997
9 2013-05-02 00:00:00.000
10 2013-05-02 00:00:00.000

 

例えば、2013/5/1 のデータを取り出そうとして、クエリの条件を WHERE d >= '2013-05-01 00:00:00.000' and d <= '2013-05-01 23:59:59.999' と書くと、それは、WHERE d >= '2013-05-01 00:00:00.000' and d <= '2013-05-02 00:00:00.000' と書いたことと同じになり、結果には 2013/5/2 のデータも含まれることになります。

 

datetime ではなく datetime2 または datetimeoffset であれば、1 ミリ秒もしくはそれ以上の精度を保てます。

 

create table t2 (n int, d datetime2)
go
insert into t2 values (9,'2013/5/1 23:59:59.999')
go
select * from t2
go

n d
----------- -----------------------
9 2013-05-01 23:59:59.9990000

 

 

 

 

datetime (Transact-SQL)

https://msdn.microsoft.com/ja-jp/library/ms187819.aspx

datetime2 (Transact-SQL)

https://msdn.microsoft.com/ja-jp/library/bb677335.aspx

datetimeoffset (Transact-SQL)

https://msdn.microsoft.com/ja-jp/library/bb630289.aspx