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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?