DATETIME 型を理解する
内部データ
DATETIME は、内部的には4バイト整数二つで表現されます。したがって、DATETIME 値は全部で8バイト必要とします。
はじめの4バイトは日付を表します。これは1900年の1月1日から何日前、何日後という形で表現されます。残りの4バイトはその日の時刻を表します。これは深夜0時からの 3 + 1/3 ミリ秒単位で計測されます。
DATETIME 型の範囲は 1753 年1月1日から9999年の12月31日です。4バイトありますから本来は1753年より前の年号も表現可能なのですが、これはユリウス暦からグレゴリオ暦への変更による影響です。
一方、SMALLDATETIME は全部で4バイトしか使いません。2バイトは1900年1月1日からの日付。残りの2バイトは、分単位で計った深夜0時からの時刻です。SMALLDATETIME では 1900年1月1日から2079年の6月6日までをサポートしています。 (大雑把に1年を常に365日として概算してみる。2バイトで表現できる上限は 0xFFFF = 65535 日。65535 / 365 = 約 179.55。したがって 1900 + 179 = 2079 年。365日*0.55=約200日。200/30 = 6.67月)
文字列から DATETIME への変換
問題。'02/12/06' という文字列は DATETIME 型でどのように変換されるでしょうか。これはそれが解釈されるコンテキストに依存します。ひとつは言語設定、もうひとつは、日付フォーマットのオプションです。T-SQL では前者は SET LANGUAGE オプションで、後者は SET DATEFORMAT オプションで指定できます。しかし、SET によって環境設定を変更するとそのセッション全ての設定を変えてしまうことになるので、自分のコードだけではなく他のコードにも影響を及ぼす可能性が出てきます。ですから、文字列そのものだけであいまいにならないような日付指定が必要となります。
方法は二つ
(a) 曖昧さのない日付フォーマット
(b) CONVERT ファンクションにおけるスタイルの指定
(a) 曖昧さのない日付フォーマット
'[yy]yymmdd[ hh:mi[:ss][.mmm]]' 例: 2006年7月12日 '20060712' または '060712' 2006年7月12日 午前7時30分 '20060712 0730'
(b) CONVERT ファンクションにおけるスタイルの指定
CONVERT ( DATETIME, '7/12/06', 103) のように、文字列の表記スタイルを指定する。
101 U.S. mm/dd/yyyy 102 ANSI yy.mm.dd 103 British/French dd/mm/yy 110 USA mm-dd-yy 111 JAPAN yy/mm/dd 112 ISO yymmdd
まるめの影響
DATETIME を扱うときには、"データの丸められ方" に注意を払う必要があります。通常、 10.9 という数値を INT 型に変換すると小数点以下が丸められ、10 になります。しかし DATETIME の場合、文字列が表す時刻に最も近い時刻に丸められます。前述の通り時刻の表現は 3 + 1/3 ミリ秒 がベースとなる単位になるので、文字列によるミリ秒の表現パターンは [0-9][0-9][0|3|7] となります (例 120 123 127 など。122 や 129 などは丸められる)。
例 DROP TABLE Table_2 CREATE TABLE Table_2 ( dt DATETIME NULL DEFAULT('000000'), sd SMALLDATETIME NULL DEFAULT('19000101') ) GO INSERT INTO Table_2 (dt) VALUES ('20060712 23:59:59') INSERT INTO Table_2 (dt) VALUES ('20060712 23:59:59.999') INSERT INTO Table_2 (dt) VALUES ( '20060712 23:59:59.998') INSERT INTO Table_2 (dt) VALUES ('20060712 23:59:59.997') SELECT * FROM Table_2 結果 dt sd 2006-07-12 23:59:59.000 1900-01-01 00:00:00 2006-07-13 00:00:00.000 1900-01-01 00:00:00 2006-07-12 23:59:59: 997 1900-01-01 00:00:00 2006-07-12 23:59:59:997 1900-01-01 00:00:00
DATETIME を扱う関数
DATEADD 日付・時間の足し算(引き算) DATEDIFF DATENAME DATEPART DAY GETDATE GETUTCDATE MONTH YEAR
関連書籍
このトピックに関するおすすめの参考資料は次です。