知らなかったでは済まされない!MySQLのDATETIMEとTIMESTAMPの落とし穴

2024-04-03

MySQLにおけるDATETIMEとTIMESTAMPの使い分け

答え: どちらを使用するかは、以下の要件によって異なります。

格納したい日時範囲

  • DATETIME: 1000-01-01 00:00:00 から 9999-12-31 23:59:59.999999 まで
  • TIMESTAMP: 1970-01-01 00:00:01 から 2038-01-19 03:14:07 まで

タイムゾーンの扱い

  • DATETIME: 格納時にタイムゾーン変換は行われず、クライアントのタイムゾーンで格納されます。
  • TIMESTAMP: 格納時にUTCへ変換され、常にUTCで格納されます。

自動更新

  • DATETIME: 自動更新されません。
  • TIMESTAMP: CURRENT_TIMESTAMP を使用すると、レコード挿入・更新時に自動的に現在のタイムスタンプが格納されます。

桁数

  • DATETIME: 19桁 (YYYY-MM-DD HH:MM:SS.fffffffff)
  • TIMESTAMP: 14桁 (YYYY-MM-DD HH:MM:SS) または 19桁 (YYYY-MM-DD HH:MM:SS.fffffffff)

その他

  • TIMESTAMPは、DATETIMEよりも新しいデータ型です。
  • TIMESTAMPは、一部の古いデータベースと互換性がない場合があります。

それぞれのデータ型が適しているケース

  • DATETIME
    • 広い範囲の日時を格納したい場合
    • タイムゾーンを保持したい場合
    • 自動更新の必要がない場合
  • TIMESTAMP
    • 2038年以前の日時を格納する場合
    • 自動更新したい場合
    • 少ない桁数で格納したい場合

補足

  • 上記はMySQL 8.0時点の情報です。バージョンによって挙動が異なる場合があります。
  • 特に、TIMESTAMP型の自動更新の挙動はバージョンによって大きく変更されています。



DATETIMEとTIMESTAMPの格納と比較

-- DATETIMEとTIMESTAMPの格納

INSERT INTO `test` (`datetime_col`, `timestamp_col`) VALUES
  ('2024-04-03 01:13:00', CURRENT_TIMESTAMP());

-- DATETIMEとTIMESTAMPの比較

SELECT `datetime_col`, `timestamp_col` FROM `test`;

-- 結果

-- datetime_col | timestamp_col
-- ------------- | -------------
-- 2024-04-03 01:13:00 | 2024-04-03 01:13:00.000000

DATETIMEとTIMESTAMPのタイムゾーン変換

-- DATETIMEのタイムゾーン変換

SET time_zone = '+09:00';

INSERT INTO `test` (`datetime_col`) VALUES ('2024-04-03 01:13:00');

SELECT `datetime_col` FROM `test`;

-- 結果

-- datetime_col
-- -------------
-- 2024-04-03 10:13:00

-- TIMESTAMPのタイムゾーン変換

SELECT `timestamp_col` FROM `test`;

-- 結果

-- timestamp_col
-- -------------
-- 2024-04-02 16:13:00.000000

TIMESTAMPの自動更新

-- TIMESTAMPの自動更新

INSERT INTO `test` (`timestamp_col`) VALUES (CURRENT_TIMESTAMP());

UPDATE `test` SET `timestamp_col` = CURRENT_TIMESTAMP();

SELECT `timestamp_col` FROM `test`;

-- 結果

-- timestamp_col
-- -------------
-- 2024-04-03 01:13:00.000000

  • 上記はあくまでサンプルコードです。実際の使用例に合わせて修正してください。
  • タイムゾーン変換の詳細は、MySQLのマニュアルを参照してください。



DATETIMEとTIMESTAMPの代わりに使用できる方法

文字列型

  • YYYY-MM-DD HH:MM:SS形式で文字列として格納できます。
  • タイムゾーンの扱いがシンプルです。
  • 他のデータ型との比較や演算が難しい場合があります。
  • インデックスを作成できない場合があります。

UNIXタイムスタンプ

  • 1970年1月1日 00:00:00 UTCからの経過秒数を格納できます。
  • 比較や演算が簡単です。
  • 人間にとって分かりにくい形式です。

その他のデータベース

  • PostgreSQLなどの他のデータベースでは、DATETIMEやTIMESTAMPとは異なるデータ型が存在する場合があります。

mysql datetime timestamp


MySQLにおけるVARCHARとVARCHAR(MAX)

VARCHAR(MAX)を使用するべき理由VARCHAR(MAX)は、次のような場合に便利です。文字列の長さが255文字を超える可能性がある場合文字列の長さが可変である場合データベースのストレージスペースを節約したい場合VARCHAR(MAX)を使用する際には、次の点に注意する必要があります。...


データベース削除は安心安全に!Linuxでシェルコマンドを使ってMySQLデータベースを削除する方法の完全マニュアル

前提条件MySQL がインストールおよび構成されているデータベースを削除する権限を持つユーザーとしてログインしている手順以下のコマンドを使用して、MySQL サーバーに接続します。上記のコマンドで、username は MySQL ユーザー名、password はパスワードに置き換えます。...


【2024年最新版】MySQL のページング処理:パフォーマンスを向上させるためのヒント

MySQL データでページングを実装する方法はいくつかありますが、それぞれに長所と短所があります。最適な方法は、データ量、アクセス頻度、パフォーマンス要件などによって異なります。主な方法LIMIT と OFFSETLIMIT と OFFSET...


【データ修正の救世主】MySQL REPLACE関数で効率的に複数レコードの文字列を置換する方法

基本的な構文文字列: 置換対象を含む文字列置換対象: 置き換えたい文字列置換後: 置換対象 を置き換える文字列例:テーブル内のすべての「AAA」を「BBB」に置き換える複数回の置換REPLACE関数を複数回ネストさせて、複数の文字列を同時に置き換えることもできます。...


【初心者向け】MySQLで「NOW() - 1 日」のデータを簡単操作で取得する方法

このチュートリアルでは、MySQLを使用して「NOW() - 1 日」のレコードを取得するSELECTクエリについて、分かりやすく解説します。対象読者MySQLの基本的な操作に慣れている方特定の日付範囲のレコードを取得する方法を知りたい方WHERE句を使用したデータ検索方法を学びたい方...