- MySQL
MySQL Incorrect datetime valueの直し方|1292
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'shipped_at' は、日時の列に、MySQL が正しい日時として認めない値を入れようとしたときのエラーです。 いちばん多いのは、以前の設定(sql_mode が緩い状態)で作られたデータの「0000-00-00」を、今の MySQL に入れようとしたときです。
| 入れようとした値 | 結果(MySQL 8.0 の既定) | 直し方 |
|---|---|---|
'0000-00-00 00:00:00' |
ERROR 1292 | NULL を入れる(列を NULL 許可に) |
'2026-02-30 00:00:00'(存在しない日) |
ERROR 1292 | 正しい日付にする |
''(空文字) |
ERROR 1292 | NULL を入れる |
'2026/10/11 09:00'(スラッシュ区切り) |
入る(2026-10-11 09:00:00) |
— |
'2026-10-11T09:00:00'(T 区切り) |
入る | — |
| 似たエラー | 意味 |
|---|---|
ERROR 1067 (42000): Invalid default value for 'shipped_at' |
列の既定値(DEFAULT)が '0000-00-00 ...' になっている。CREATE・ALTER で出る |
ERROR 1525 (HY000): Incorrect DATETIME value: '0000-00-00 00:00:00' |
WHERE で = '0000-00-00 00:00:00' と比べた。探すときに出る |
確認環境:MySQL 8.0.46(sql_mode は既定)、PyMySQL 2.2.8、MariaDB Connector/J 2.7.6(確認日 2026年10月11日)。sql_mode を空にして「以前のデータ」を作り、既定の設定に戻して再現しました。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQL Incorrect datetime valueの直し方|1292」
なぜ出るのか:sql_mode の NO_ZERO_DATE と strict モード
SELECT @@sql_mode;
-- ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
MySQL 8.0 の既定の sql_mode には、次の3つが入っています(MySQL 公式マニュアル)。
| モード | 止めるもの |
|---|---|
NO_ZERO_DATE |
'0000-00-00' |
NO_ZERO_IN_DATE |
月や日だけが 0 の日付('1990-00-15' など) |
STRICT_TRANS_TABLES(strict モード) |
上の2つを「警告」ではなく「エラー」にする |
sql_mode を空にして作られたデータベースでは、これらの値がエラーにならずに保存されています。確認環境でも、sql_mode を空にすると、'0000-00-00'・'1990-00-15' はそのまま入り、'2026-02-30' は 0000-00-00 に変わって警告(1264)だけが出ました。
id name shipped_at birthday
1 佐藤 0000-00-00 00:00:00 0000-00-00
2 鈴木 0000-00-00 00:00:00 1990-00-15
3 高橋 0000-00-00 00:00:00 0000-00-00 ← 2026-02-30 を入れた行
このデータを、既定の sql_mode のサーバーに移すと、INSERT で 1292 になります(ダンプの取り込みも同じ)。
再現:既存のテーブルを ALTER すると 1067
データを入れていないのにエラーになるのが、このパターンです。
-- 以前の設定で作られたテーブル
CREATE TABLE legacy (
id int PRIMARY KEY,
shipped_at datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
...
);
mysql> ALTER TABLE legacy ADD COLUMN memo varchar(10);
ERROR 1067 (42000): Invalid default value for 'shipped_at'
追加しようとした memo ではなく、ほかの列(shipped_at)の既定値がエラーになっています。ALTER はテーブルを作り直すため、既定値も今の sql_mode で確かめられるからです。
0000-00-00 の行を探す(= で比べると 1525)
mysql> SELECT id FROM legacy WHERE shipped_at = '0000-00-00 00:00:00';
ERROR 1525 (HY000): Incorrect DATETIME value: '0000-00-00 00:00:00'
既定の sql_mode では、探そうとするだけでエラーになりました。 次の書き方なら、エラーにならずに見つかりました。
| 書き方 | 結果 |
|---|---|
WHERE shipped_at = '0000-00-00 00:00:00' |
ERROR 1525 |
WHERE YEAR(shipped_at) = 0 |
見つかる |
WHERE shipped_at < '1000-01-01' |
見つかる |
WHERE shipped_at = 0 |
見つかる |
月・日だけが 0:WHERE MONTH(birthday) = 0 OR DAY(birthday) = 0 |
見つかる(1990-00-15 も含む) |
直し方:NULL を入れられる列にして、0 の日付を NULL にする
「0000-00-00」は、ほとんどの場合「日付が無い(未設定)」の意味で使われています。NULL で表すのが正しい形です。
-- 1. 列を NULL 許可にし、既定値を NULL にする
ALTER TABLE legacy MODIFY shipped_at datetime NULL DEFAULT NULL;
-- 2. 0 の日付を NULL にする
UPDATE legacy SET shipped_at = NULL WHERE YEAR(shipped_at) = 0;
UPDATE legacy SET birthday = NULL WHERE MONTH(birthday) = 0 OR DAY(birthday) = 0;
-- 3. これで ALTER も通る
ALTER TABLE legacy ADD COLUMN memo varchar(10);
id name shipped_at birthday memo
1 佐藤 NULL NULL NULL
2 鈴木 NULL NULL NULL
3 高橋 NULL NULL NULL
確認環境では、既定の sql_mode のまま、この順番で直せました。直す前に、アプリやレポートが「0000-00-00」を前提にしていないか(WHERE shipped_at = '0000-00-00' で未出荷を判定している、など)を確かめ、IS NULL に書き換えます。
移行のときにまとめて直す
ダンプを取り込む前に直せない場合は、取り込むセッションだけ sql_mode を緩め、取り込んだあとに上の UPDATE で直します。
SET SESSION sql_mode = ''; -- このセッションだけ(サーバー全体は変えない)
SOURCE dump.sql;
-- 取り込み後、0 の日付を NULL にする
サーバー全体の sql_mode から NO_ZERO_DATE や STRICT を外すのは避けます。 存在しない日付(2月30日など)が、黙って 0000-00-00 で保存されるようになるためです。なお、NO_ZERO_DATE・NO_ZERO_IN_DATE は公式マニュアルで非推奨とされ、将来は strict モードに含まれる予定と書かれています。
アプリからの見え方
0 の日付が残っていると、アプリではエラーにならずに、別の値に化けて見えることがあります。
| ドライバー | 0000-00-00 00:00:00 の読み取り結果 |
|---|---|
| PyMySQL 2.2.8 | '0000-00-00 00:00:00'(文字列)。ほかの行は datetime なので、型が混ざる |
| MariaDB Connector/J 2.7.6 | getTimestamp・getObject(LocalDateTime)・getDate のどれも null |
| MySQL Connector/J | 公式ドキュメントでは、zeroDateTimeBehavior の既定値は EXCEPTION(例外)。CONVERT_TO_NULL を指定すると NULL として読める |
同じデータでも、ドライバーによって「文字列」「null」「例外」と結果が分かれます。 ドライバーの設定で隠すより、データを NULL に直すのが確実です。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | エラーの番号 | 1292(値)、1067(既定値)、1525(WHERE の比較) |
| 2 | sql_mode | SELECT @@sql_mode;(移行元と移行先を比べる) |
| 3 | 0 の日付の行 | WHERE YEAR(列) = 0、MONTH(列) = 0 OR DAY(列) = 0 |
| 4 | 列の既定値 | SHOW CREATE TABLE で DEFAULT '0000-00-00 ...' を探す |
| 5 | 直す | NULL 許可・既定値 NULL にして、UPDATE で NULL に |
| 6 | アプリ | = '0000-00-00' の判定を IS NULL に書き換える |
よくある質問
Q. 「2026/10/11」のようなスラッシュ区切りの日付は入りますか。
A. 確認環境では入りました(2026-10-11 00:00:00 として保存)。ただし、'2026-02-30' のような存在しない日付や空文字は 1292 になります。アプリ側で日付の形式と値を確かめてから入れます。
Q. INSERT IGNORE を使えば入りますか。
A. 公式マニュアルでは、INSERT IGNORE なら '0000-00-00' が警告つきで入るとされています。ただし、それは不正なデータを入れ続けることなので、移行の一時的な手段にとどめます。
まとめ
- sql_mode の NO_ZERO_DATE と strict モードで、
0000-00-00がエラーになる - 多いのは、sql_mode が緩い状態で作られたデータの移行
- 既定値が
'0000-00-00'の列があると、ALTER で 1067 = '0000-00-00'で探すと 1525。YEAR(列) = 0で探す- 直し方は NULL 許可にして、0 の日付を NULL に。サーバーの sql_mode は緩めない
- ドライバーによって文字列・null・例外に化ける。データを直すのが確実
参考・出典
確認日はいずれも 2026年10月11日です。
- MySQL 8.0 Reference Manual「Server SQL Modes」:https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
- MySQL Connector/J Developer Guide「Datetime types processing」:https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-datetime-types-processing.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQL Incorrect datetime valueの直し方|1292」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。