1. MySQLで現在時刻を取得する最短SQL
MySQLで現在時刻を取得したい場合、まず覚えるべき関数は NOW() と CURRENT_TIMESTAMP です。用途別に最短SQLを示します。
1.1 今の日時を取得する(基本)
SELECT NOW();
または
SELECT CURRENT_TIMESTAMP;
どちらも 現在の日時(YYYY-MM-DD HH:MM:SS) を返します。
同一クエリ内では「クエリ開始時点」の時刻が固定されます。
用途
ログ記録
データ作成日時の取得
基準時刻の取得
よくある失敗
アプリ側のタイムゾーンとDB側のタイムゾーンが異なり「時刻がずれる」
→SELECT @@session.time_zone;で確認
1.2 今日の日付だけ取得する
SELECT CURDATE();
返却形式:
YYYY-MM-DD型は DATE型(日時ではなく日付のみ)
用途
「今日のデータ」検索
日単位集計
注意点
NOW()と違い時刻は含まれません。期間検索で時刻も必要な場合は
NOW()を使う。
1.3 現在の時刻だけ取得する
SELECT CURTIME();
返却形式:
HH:MM:SS型は TIME型(時間のみ)
用途
バッチ実行時刻の表示
ログの時刻のみ出力
つまずきポイント
日付は含まれないため、日時比較には使えません。
1.4 UTCで現在時刻を取得する(重要)
SELECT UTC_TIMESTAMP();
サーバーのタイムゾーンに依存せず、UTC(協定世界時) を返します。
グローバルサービスでは推奨される取得方法。
実務での基本方針
保存はUTC
表示時にローカルタイムへ変換
注意点
アプリ側が既にUTC変換している場合、二重変換に注意。
1.5 ミリ秒・マイクロ秒を含めて取得する
SELECT NOW(3); -- ミリ秒(小数点以下3桁)
SELECT NOW(6); -- マイクロ秒(小数点以下6桁)
MySQL 5.6.4以降で使用可能。
高精度ログ・トランザクション監査で利用。
よくある誤解
NOW()だけでは小数点以下は取得できません。カラム側も
DATETIME(6)など精度指定が必要。
1.6 用途別の最適関数まとめ(迷ったらここ)
| 用途 | 推奨関数 |
|---|---|
| 一般的な現在日時取得 | NOW() |
| テーブルのデフォルト値 | CURRENT_TIMESTAMP |
| 日付だけ必要 | CURDATE() |
| 時刻だけ必要 | CURTIME() |
| UTCで統一管理 | UTC_TIMESTAMP() |
| 高精度ログ | NOW(6) |
つまずきやすい重要ポイント
NOW()とCURRENT_TIMESTAMPは実質同義(取得値は同じ)同一クエリ内では時刻は固定される
タイムゾーン設定により表示が変わる
マイクロ秒を扱う場合はカラム定義も精度指定が必要
2. NOW() / CURRENT_TIMESTAMP / SYSDATE() の違い
現在時刻を取得する関数は複数ありますが、最も混乱しやすいのが NOW()・CURRENT_TIMESTAMP・SYSDATE() の違いです。
ここを正確に理解していないと、ログやトランザクション処理で予期しない挙動になります。
2.1 NOW() と CURRENT_TIMESTAMP は実質同義
SELECT NOW(), CURRENT_TIMESTAMP;
どちらも 現在の日時(DATETIME値) を返します。
同一クエリ内では「クエリ開始時点」の時刻で固定されます。
CURRENT_TIMESTAMPは関数呼び出し形式でも使用可能:
SELECT CURRENT_TIMESTAMP();
実務での使い分け
| 用途 | 推奨 |
|---|---|
| 単純な取得 | NOW() |
| テーブルのDEFAULTやON UPDATE | CURRENT_TIMESTAMP |
重要ポイント
取得値の意味は同じ。
違いは「構文上の扱い(DEFAULT指定可)」が主。
型の違いではない(誤解しやすい点)。
2.2 SYSDATE() は“評価時点”の時刻を返す
SYSDATE() は NOW() に似ていますが、時刻の固定タイミングが異なります。
SELECT NOW(), SLEEP(2), NOW();
結果(例):
2025-02-23 14:00:00
2025-02-23 14:00:00
SELECT SYSDATE(), SLEEP(2), SYSDATE();
結果(例):
2025-02-23 14:00:00
2025-02-23 14:00:02
違いの本質
| 関数 | 時刻が固定されるタイミング |
|---|---|
NOW() | クエリ開始時点 |
SYSDATE() | 実行評価時点 |
つまり SYSDATE() は、同一クエリ内でも時間経過で値が変わります。
2.3 トランザクションやレプリケーションでの注意点
NOW() はクエリ開始時に固定されるため、
トランザクション内で一貫した基準時刻を扱う場合に安全です。
一方 SYSDATE() は実行タイミング依存のため、
レプリケーション(複製環境)
バッチ処理
ログ一括処理
では再現性に影響する可能性があります。
原則
基準時刻を固定したい →
NOW()毎回その瞬間の時刻が必要 →
SYSDATE()(限定用途)
2.4 補足:CURRENT_DATE / CURRENT_TIME / LOCALTIME
MySQLでは以下も利用できます:
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT LOCALTIME;
CURRENT_DATE→CURDATE()と同義CURRENT_TIME→CURTIME()と同義LOCALTIME→NOW()と同義
つまずきやすい点
どれも「見た目の違い」であり、機能差はほぼありません。
可読性を優先し、プロジェクト内で統一するのが安全。
この章の重要まとめ
NOW()とCURRENT_TIMESTAMPは実質同じ意味。SYSDATE()は評価時刻ベースで挙動が異なる。基準時刻を固定する処理では
NOW()を使うのが基本。DEFAULTやON UPDATEには
CURRENT_TIMESTAMPを使用。
3. 現在時刻の表示形式を変える
MySQLで NOW() などを使って取得した現在時刻は、標準では YYYY-MM-DD HH:MM:SS 形式で表示されます。しかし、実務では以下のような要望が頻繁に発生します。
年月日だけ表示したい
YYYY/MM/DD形式にしたい日本語表記にしたい(例:2025年02月23日)
ミリ秒まで表示したい
このときに使用するのが DATE_FORMAT() 関数(日時を任意形式に変換する関数) です。
3.1 DATE_FORMAT() の基本構文
DATE_FORMAT(日時, 'フォーマット文字列')
例:現在時刻を YYYY/MM/DD HH:MM 形式に変換
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');
出力例:
2025/02/23 14:35
よく使う指定子
| 指定子 | 意味 | 例 |
|---|---|---|
%Y | 4桁の年 | 2025 |
%m | 2桁の月 | 02 |
%d | 2桁の日 | 23 |
%H | 24時間表記の時 | 14 |
%i | 分 | 35 |
%s | 秒 | 50 |
%f | マイクロ秒 | 123456 |
注意点
フォーマット指定子は大文字・小文字で意味が異なる場合がある。
%hは12時間表記、%Hは24時間表記。
3.2 よくあるフォーマット例(実務で頻出)
1. スラッシュ区切り
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d');
2. 日本語表記
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日');
3. 秒なし表示
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');
つまずきやすいポイント
文字列として返るため、数値計算には使えない。
比較や検索には元のDATETIME型を使うべき。
3.3 日付部分・時間部分だけを取り出す方法
フォーマット変換ではなく、型を維持したまま取得する方法もあります。
SELECT DATE(NOW()); -- 日付のみ(DATE型)
SELECT TIME(NOW()); -- 時刻のみ(TIME型)
SELECT YEAR(NOW()); -- 年だけ
SELECT MONTH(NOW()); -- 月だけ
SELECT DAY(NOW()); -- 日だけ
実務での使い分け
| 目的 | 推奨 |
|---|---|
| 表示用整形 | DATE_FORMAT |
| 計算・比較 | DATE() / TIME() |
3.4 マイクロ秒を含めて表示する
高精度ログが必要な場合:
SELECT NOW(6);
フォーマット指定:
SELECT DATE_FORMAT(NOW(6), '%Y-%m-%d %H:%i:%s.%f');
重要注意点
カラム側も
DATETIME(6)またはTIMESTAMP(6)にしないと精度は保存されない。MySQL 5.6.4未満では使用不可(環境依存)。
よくある失敗
DATE_FORMAT()を WHERE句で使い、インデックスが効かなくなる。NG例:
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-23'推奨:
WHERE created_at >= '2025-02-23 00:00:00' AND created_at < '2025-02-24 00:00:00'
表示用フォーマットをそのまま保存してしまう(検索性能低下)
この章の重要まとめ
表示形式変更は
DATE_FORMAT()を使用。計算・比較は型を保ったまま行う。
マイクロ秒を扱う場合はカラム定義も精度指定。
WHERE句での関数利用はパフォーマンス低下の原因。
4. 現在時刻を使った日時計算
MySQLでは、現在時刻を基準に「◯時間後」「◯日前」「過去◯日間」といった計算が頻繁に行われます。
実務で最も多いのは 「過去24時間のデータ取得」 です。
日時計算の基本は INTERVAL(時間単位を指定して加減算する構文) です。
4.1 INTERVAL で加算・減算する
1時間後を取得
SELECT NOW() + INTERVAL 1 HOUR;
3日前を取得
SELECT NOW() - INTERVAL 3 DAY;
1ヶ月後を取得
SELECT NOW() + INTERVAL 1 MONTH;
使用できる主な単位
| 単位 | 意味 |
|---|---|
| SECOND | 秒 |
| MINUTE | 分 |
| HOUR | 時 |
| DAY | 日 |
| WEEK | 週 |
| MONTH | 月 |
| YEAR | 年 |
よくある失敗
INTERVAL 1 DAYのDAYを小文字にしても動くが、チーム内で統一すべき。月末計算では日数が変動するため、期待通りにならない場合がある(例:1月31日 + 1ヶ月)。
4.2 過去24時間のデータを取得する(最頻出パターン)
SELECT *
FROM users
WHERE created_at >= NOW() - INTERVAL 1 DAY;
意味
「今この瞬間から24時間前まで」を対象にする。
注意点
CURDATE()を使うと「今日の0時基準」になるため意味が変わる。
例(今日のデータ):
SELECT *
FROM users
WHERE created_at >= CURDATE();
違いを理解することが重要
| 書き方 | 意味 |
|---|---|
NOW() - INTERVAL 1 DAY | 直近24時間 |
CURDATE() | 今日0:00以降 |
4.3 DATEDIFF() で日数差を求める
SELECT DATEDIFF('2025-03-01', '2025-02-23');
結果:
6
単位は「日」
時刻部分は無視される
注意点
引数の順序で符号が変わる。
時刻単位の差は計算できない。
4.4 TIMESTAMPDIFF() で時間・分・秒を計算
SELECT TIMESTAMPDIFF(HOUR,
'2025-02-23 12:00:00',
'2025-02-23 18:30:00');
結果:
6
分単位
SELECT TIMESTAMPDIFF(MINUTE,
'2025-02-23 12:00:00',
'2025-02-23 12:30:00');
秒単位
SELECT TIMESTAMPDIFF(SECOND,
'2025-02-23 12:00:00',
'2025-02-23 12:00:45');
実務用途
セッション滞在時間計算
有効期限チェック
タイムアウト判定
4.5 月初・月末の取得(実務でハマるポイント)
今月の1日を取得:
SELECT DATE_FORMAT(NOW(), '%Y-%m-01');
翌月の1日:
SELECT DATE_FORMAT(NOW() + INTERVAL 1 MONTH, '%Y-%m-01');
注意点
月末日は固定値ではない。
期間検索では「>= 開始 AND < 翌月1日」が安全。
よくある失敗まとめ
BETWEENで日付だけ指定して時刻を含め忘れるDATE(created_at)をWHERE句で使いインデックスが無効化月計算で31日問題にハマる
NOW()とCURDATE()の違いを誤解
この章の重要まとめ
日時計算は
INTERVALが基本。直近24時間は
NOW() - INTERVAL 1 DAY。日単位は
DATEDIFF()、細かい単位はTIMESTAMPDIFF()。月単位の計算は終端条件に注意。
5. 期間検索はBETWEENよりこの書き方が安全
MySQLで期間検索を行う際、多くの初心者が BETWEEN を使用します。しかし、時刻の扱いを誤ると意図しない結果になることが多く、実務ではより安全な書き方が推奨されます。
5.1 BETWEEN の基本と落とし穴
よくある書き方
SELECT *
FROM orders
WHERE order_date BETWEEN '2025-02-01' AND '2025-02-10';
一見問題なさそうですが、これは内部的には次と同じ意味になります:
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date <= '2025-02-10 00:00:00'
つまり、2月10日の0時以降のデータは含まれません。
5.2 安全な書き方(推奨)
推奨構文
SELECT *
FROM orders
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date < '2025-02-11 00:00:00';
ポイント
終端は「翌日0時未満」で指定する
<= 23:59:59よりも安全(マイクロ秒対応)
5.3 今日のデータを取得する正しい方法
NG例:
WHERE DATE(created_at) = CURDATE();
問題点:
列に関数をかけているため、インデックス(索引)が無効化される
大量データでは性能低下
推奨:
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
これにより:
インデックスが効く
高速検索が可能
日付の境界問題を回避
5.4 過去7日・過去30日の安全な書き方
過去7日
WHERE created_at >= NOW() - INTERVAL 7 DAY;
過去30日
WHERE created_at >= NOW() - INTERVAL 30 DAY;
注意点
CURDATE() - INTERVAL 7 DAYは「今日0時基準」NOW() - INTERVAL 7 DAYは「現在時刻基準」要件により使い分ける
5.5 インデックスを効かせるための重要ルール
NG:
WHERE DATE(created_at) = '2025-02-23';
OK:
WHERE created_at >= '2025-02-23 00:00:00'
AND created_at < '2025-02-24 00:00:00';
理由:
インデックスは「列そのもの」に対して効く
列に関数を適用すると索引が使えない(フルスキャン)
よくある失敗まとめ
BETWEENの終端に時刻を含め忘れる23:59:59指定でマイクロ秒を漏らすWHERE句で
DATE()を使用し性能低下基準が「今」なのか「今日0時」なのかを曖昧にする
この章の重要まとめ
期間検索は
>= 開始 AND < 終了が安全。BETWEENは境界の扱いに注意。インデックスを効かせるため、列に関数をかけない。
NOW()基準とCURDATE()基準を明確に使い分ける。
6. DEFAULT CURRENT_TIMESTAMP と ON UPDATE(テーブル設計の基本)
データベース設計では、作成日時(created_at)と更新日時(updated_at)を自動管理するのが一般的です。
MySQLでは CURRENT_TIMESTAMP を使うことで、挿入時・更新時に自動で現在時刻を設定できます。
6.1 作成日時を自動セットする(DEFAULT CURRENT_TIMESTAMP)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
動作:
INSERT INTO users (name) VALUES ('Alice');
→ created_at に現在時刻が自動挿入される。
ポイント
CURRENT_TIMESTAMPは DEFAULT に使用可能。NOW()は DEFAULT には直接使用不可。
よくある失敗
created_at DATETIME DEFAULT NOW(); -- エラー
理由:
MySQLでは DEFAULT には関数を直接指定できない(例外は CURRENT_TIMESTAMP)。
6.2 更新日時を自動更新する(ON UPDATE)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
動作:
UPDATE users SET name = 'Bob' WHERE id = 1;
→ updated_at が自動的に現在時刻へ更新。
用途
最終ログイン管理
データ更新履歴
監査ログ
6.3 DATETIME と TIMESTAMP の違い(重要)
| 型 | 範囲 | タイムゾーン影響 |
|---|---|---|
| DATETIME | 1000年〜9999年 | なし |
| TIMESTAMP | 1970〜2038年 | あり |
違いの本質
TIMESTAMPは内部的にUTCで保存し、表示時にセッションTZへ変換。DATETIMEは文字通りその値を保存(変換なし)。
使い分け指針
| ケース | 推奨型 |
|---|---|
| ログ管理 | TIMESTAMP |
| 将来日付(2038年以降) | DATETIME |
| TZ変換不要の固定値 | DATETIME |
6.4 CURRENT_TIMESTAMP は DATETIME でも使える
MySQL 5.6以降では、DATETIME 型でも DEFAULT および ON UPDATE に CURRENT_TIMESTAMP を指定可能です。
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
注意点
古いMySQLでは制限がある(環境依存)。
精度指定が必要な場合:
DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
6.5 NOW() を使いたい場合の代替方法(トリガー)
CREATE TRIGGER set_created_at
BEFORE INSERT ON logs
FOR EACH ROW
SET NEW.created_at = NOW();
用途
複雑な初期値ロジック
条件付き日時設定
注意点
トリガーはデバッグが難しい。
不要な場合は避ける。
よくある設計ミス
created_atとupdated_atの両方に ON UPDATE を付けてしまうDATETIME と TIMESTAMP の挙動を混同
タイムゾーン設計を後回しにする
この章の重要まとめ
DEFAULT には
CURRENT_TIMESTAMPを使う。更新管理には
ON UPDATE CURRENT_TIMESTAMP。型選択は「タイムゾーン影響」と「2038年問題」で判断。
精度が必要なら
(6)指定を忘れない。
7. タイムゾーン設計(UTCで保存してローカル表示する)
現在時刻を扱う際、タイムゾーン(時間帯)設計を誤ると時刻ズレや二重変換が発生します。
実務では原則として「保存はUTC、表示はローカル変換」が安全です。

7.1 現在のタイムゾーンを確認する
まず、MySQLがどのタイムゾーンで動いているかを確認します。
SELECT @@global.time_zone, @@session.time_zone;
@@global.time_zone→ サーバー全体の設定@@session.time_zone→ 現在の接続セッションの設定SYSTEMの場合はOS設定に依存
よくある問題
本番と開発でOSタイムゾーンが異なる
アプリ側でUTC変換しているのにDB側でも変換してしまう
7.2 セッション単位でタイムゾーンを変更する
SET time_zone = 'Asia/Tokyo';
またはUTCへ統一:
SET time_zone = '+00:00';
重要ポイント
接続が切れると元に戻る
接続プール利用時はアプリ設定を確認する
7.3 UTCで保存する理由(実務原則)
推奨方針
データはUTCで保存
表示時にユーザーのタイムゾーンへ変換
理由:
国際対応が容易
夏時間(DST)問題を回避
サーバー移設時の影響を最小化
UTC取得:
SELECT UTC_TIMESTAMP();
7.4 CONVERT_TZ() でタイムゾーン変換
UTC → JST変換例:
SELECT CONVERT_TZ('2025-02-23 05:35:00', '+00:00', '+09:00');
タイムゾーン名指定:
SELECT CONVERT_TZ('2025-02-23 05:35:00', 'UTC', 'Asia/Tokyo');
実務例
SELECT CONVERT_TZ(created_at, 'UTC', 'Asia/Tokyo')
FROM users;
7.5 CONVERT_TZ() が NULL になる原因
もし NULL が返る場合:
MySQLのタイムゾーンテーブルが未ロード
指定したタイムゾーン名が存在しない
Linuxでのロード例:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
注意点
本番環境では権限と再起動を確認
Docker環境ではzoneinfoが含まれていない場合あり
7.6 サーバー全体のタイムゾーン変更
設定ファイル(my.cnf / my.ini):
[mysqld]
default_time_zone = '+00:00'
再起動後に確認:
SELECT @@global.time_zone;
重要
本番環境での変更は影響範囲を必ず確認
既存データの扱いに注意(表示だけが変わる場合あり)
よくある失敗
UTC保存せずローカル保存して後から国際対応
アプリ側とDB側で二重変換
DATETIME型でTZを意識せず設計
テスト環境と本番でTZが異なる
この章の重要まとめ
保存はUTC、表示で変換が基本。
UTC_TIMESTAMP()を活用する。CONVERT_TZ()使用時はTZテーブル確認。タイムゾーンは環境差異を必ず意識する。
8. 実務でそのまま使える現在時刻の活用例
ここでは、MySQLの現在時刻を実際の開発・運用でどのように使うかを具体的なSQL付きで解説します。
そのままコピペして使える形にしています。
8.1 ログ記録に現在時刻を自動で入れる
テーブル作成
CREATE TABLE system_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
level VARCHAR(50),
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ログ追加
INSERT INTO system_logs (level, message)
VALUES ('ERROR', 'DB接続に失敗しました');
ポイント
created_atは自動挿入アプリ側で時刻を渡す必要なし
監査・障害調査で必須設計
よくある失敗
アプリ側とDB側で時刻を二重管理
タイムゾーン未統一で時刻不整合
8.2 最終ログイン時刻を更新する
テーブル設計
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
ログイン時更新
UPDATE users
SET last_login = NOW()
WHERE id = 1;
注意点
ON UPDATEは列が変更されたときのみ発動変更がないUPDATEでは更新されない場合あり
8.3 バッチ処理で基準時刻を固定する
長時間処理では、基準時刻を固定するのが安全です。
SET @base_time = NOW();
SELECT *
FROM orders
WHERE created_at >= @base_time - INTERVAL 1 DAY;
理由
処理途中で時刻が変わらない
一貫性が保てる
8.4 今日・昨日・直近7日の集計
今日の売上
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
昨日の売上
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE() - INTERVAL 1 DAY
AND created_at < CURDATE();
直近7日
SELECT COUNT(*)
FROM users
WHERE created_at >= NOW() - INTERVAL 7 DAY;
重要
WHERE句で列に関数をかけない
インデックスを活かす書き方を徹底
8.5 有効期限チェック(セッション・トークン管理)
SELECT *
FROM sessions
WHERE expires_at > NOW();
期限切れ削除
DELETE FROM sessions
WHERE expires_at <= NOW();
よくある失敗
CURDATE()を使って時刻を無視してしまうUTC保存しているのにローカルNOW()で比較
8.6 期限が◯時間後のデータ取得
SELECT *
FROM coupons
WHERE expires_at <= NOW() + INTERVAL 1 HOUR;
用途:
有効期限アラート
期限切れ通知
実務で必ず意識すべきこと
取得基準が「今」なのか「今日0時」なのか明確にする
インデックスを活かす条件式を書く
タイムゾーン設計を最初に決める
NOW()とUTC_TIMESTAMP()を混在させない
この章の重要まとめ
ログ・監査・更新管理には
CURRENT_TIMESTAMP集計は
>= AND <形式で安全にセッション管理は
NOW()比較基準時刻を固定して一貫性を保つ
9. よくある質問(FAQ)
ここでは、MySQLの現在時刻に関して特に多い疑問と、実務でつまずきやすいポイントを整理します。
9.1 NOW() と CURRENT_TIMESTAMP の違いは?
結論:取得値の意味は同じ。
SELECT NOW(), CURRENT_TIMESTAMP;
どちらも現在日時を返します。
違いは主に構文上の扱い
CURRENT_TIMESTAMPはDEFAULTやON UPDATEに使用可能NOW()はDEFAULTには直接使えない
注意
型が違うわけではない
取得値の精度は引数
(6)などで指定可能
9.2 SYSDATE() は使うべき?
SYSDATE() は「評価時点」の時刻を返します。
SELECT SYSDATE(), SLEEP(2), SYSDATE();
同一クエリ内でも値が変わる可能性があります。
使うべき場面
その瞬間の実時間を厳密に記録したい場合
避けるべき場面
レプリケーション
一貫性が重要なトランザクション処理
基本は NOW() を使えば問題ありません。
9.3 時刻がずれる原因は?
主な原因:
サーバーのタイムゾーン設定
セッションのタイムゾーン設定
アプリ側との二重変換
TIMESTAMP型の自動変換
確認:
SELECT @@global.time_zone, @@session.time_zone;
対策
UTC保存を原則にする
表示時のみ変換
アプリとDBで方針を統一
9.4 CONVERT_TZ() が NULL になる
原因:
タイムゾーンテーブル未ロード
タイムゾーン名の誤り
対処:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Docker環境では特に要注意。
9.5 BETWEEN で範囲がずれる
NG:
WHERE created_at BETWEEN '2025-02-01' AND '2025-02-10';
安全:
WHERE created_at >= '2025-02-01 00:00:00'
AND created_at < '2025-02-11 00:00:00';
理由:
終端時刻問題
マイクロ秒漏れ
インデックス効率
9.6 DATETIME と TIMESTAMP の選び方は?
国際対応・UTC管理 → TIMESTAMP
2038年以降や固定日時 → DATETIME
設計時に必ず決めること。
9.7 マイクロ秒が保存されない
原因:
カラム定義に精度指定なし
修正:
created_at DATETIME(6)
この章の重要まとめ
基本は
NOW()とCURRENT_TIMESTAMP期間検索は
>= AND <タイムゾーンはUTC保存が安全
型選択と精度指定を忘れない
10. まとめ
本記事では、MySQLで現在時刻を取得・操作・管理する方法を、実務視点で整理しました。
最後に、最低限これだけ理解しておけば安全というポイントをまとめます。
10.1 現在時刻の取得(基本)
一般取得 →
NOW()テーブルDEFAULT・更新管理 →
CURRENT_TIMESTAMP日付のみ →
CURDATE()時刻のみ →
CURTIME()UTC取得 →
UTC_TIMESTAMP()高精度 →
NOW(6)
原則
迷ったら
NOW()を使えば問題なし。設計用途なら
CURRENT_TIMESTAMP。
10.2 期間検索は「>= AND <」が鉄則
安全な書き方:
WHERE created_at >= '開始'
AND created_at < '終了'
理由:
終端時刻の漏れ防止
マイクロ秒対応
インデックスが効く
NG例
WHERE DATE(created_at) = CURDATE();
列に関数をかけないこと。
10.3 日時計算の基本
加減算 →
INTERVAL日数差 →
DATEDIFF()時間差 →
TIMESTAMPDIFF()
基準が「今」か「今日0時」かを常に意識する。
10.4 タイムゾーン設計の原則
保存はUTC
表示時に変換
アプリとDBで方針統一
確認コマンド:
SELECT @@global.time_zone, @@session.time_zone;
10.5 テーブル設計のベストプラクティス
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
監査・ログ・更新管理は標準装備
精度が必要なら
(6)を指定
実務で最も重要な4点
NOW()とCURRENT_TIMESTAMPの違いを誤解しない期間検索は
>= AND <UTC保存を原則にする
型選択(DATETIME / TIMESTAMP)を設計段階で決める
MySQLの現在時刻処理は、ログ管理・売上集計・認証管理・バッチ処理など、あらゆる場面の基礎になります。
ここで解説した原則を守れば、時刻ズレ・境界バグ・性能劣化の多くを回避できます。


