挨拶
初めまして、日本システム開発株式会社の鈴木です。
技術者として更なる向上を目指すためQiitaアウトプットをする取り組みを行っています。
技術者としては経験が浅く発信内容はとにかく試したものの覚書になります。
今回はOracle DBのテーブル定義を参考にSQL Serverにてテーブルを作成する際に、日付を保持したいときのデータ型で勘違いがあったため、調査結果をまとめたものになります。
Oracle DB
Oracleでは日付を保持するためのデータ型は以下の4種類(時刻のみなら+1種類)です(参考)。
・TT_DATE
・DATE
・TT_TIMESTAMP
・TIMESTAMP
・TIME(時刻のみを保持する型で、日付を保持することはできません)
TT_DATEは日付のみを格納する型で書式はYYYY-MM-DDです。書式からもわかる通り時刻を記録することはできません。一方DATE、TT_TIMESTAMP、TIMESTAMPは時刻も含めることができます。書式はYYYY-MM-DD HH:MI:SSになります。TT_TIMESTAMP、TIMESTAMPはミリ秒まで記録することができますが、範囲はTT_TIMESTAMPが1753年1月1日の午前0時から、TIMESTAMPが紀元前4712年1月1日からになります。
SQL Server
筆者が勘違いしていたSQL Serverの日付型は以下です(参考)。
・date
・smalldatetime
・datetime
・datetime2
・datetimeoffset
・time(時刻のみを保持する型で、日付を保持することはできません)
dateはOracleのDATE同様YYYY-MM-DD書式で表現される時刻を持たない日付のデータ型です。smalldatetime、datetime、datetime2はOracleのTIMESTAMPと同様時刻まで含めた日付型で、smalldatetimeはミリ秒を記録できず(OracleのTT_TIMESTAMPに相当)、datetime2が100ナノ秒単位でミリ秒を記録できます(OracleのTIMESTAMPに相当)。
ここで、Oracleにはdatetime型は存在しないですが、SQL Serverには日付型の値の管理が目的ではないTIMESTAMP型が存在します。SQL ServerにおけるTIMESTAMP型はそのレコードの最終更新日時をSQL Serverが記録するためのバイナリデータ型です。システムが更新することを前提としているため、ユーザによるUPDATE文の発行はできず(TIMESTAMP型要素を更新しようとするとエラーにより失敗する)、挿入時もエラーにより失敗します。そのため、SELECTによる値の取得時は日時が表示されますが、日時の値を管理することはできません。他のDBMSから移行する場合は上記のdatetime系のデータ型を使用する必要があります(参考)。
(参考)MySQL
MySQLでは以下の3種類の日付管理型があります(参考)。
・DATE
・DATETIME
・TIMESTAMP
DATEは日付のみ、DATETIMEは日時、TIMESTAMPはミリ秒まで管理します。それぞれOracleではDATE、TT_DATE、TIMESTAMPに対応しています。
(参考)SQLite
SQLiteは特徴的で、日付を管理する型がありません。文字列型で保存し、使用時に逐次変換することになります。