MySQLアップグレード後の「ERROR 1067: Invalid default value」の解決方法

intermediate🗄️ MySQL2026-06-24| MySQL 5.7+, MySQL 8.0+, MariaDB 10.2+, Linux (Ubuntu/CentOS), macOS, Windows (XAMPP/WAMP)

Error Message

ERROR 1067 (42000): Invalid default value for 'created_at'
#mysql#データベース管理#sql-mode#devops#バックエンド

アップグレードの落とし穴MySQL 5.6のような古いデータベースからバージョン8.0へアップグレードすることは、通常、パフォーマンスの向上につながります。しかし、マイグレーションの実行やレガシーなSQLダンプのインポート時に、多くの開発者が壁に突き当たります。突然、単純な ALTER TABLE コマンドが次のような厄介なエラーで失敗するのです。

ERROR 1067 (42000): Invalid default value for 'created_at'

このエラーは通常、デフォルト値として '0000-00-00 00:00:00' を使用している TIMESTAMP 型や DATETIME 型のカラムが対象となります。古い環境では長年問題なく動作していましたが、最新の MySQL バージョンではデータの整合性をより厳格に保護するようになっています。

根本原因:厳密モード(Strict Mode)これはコードのバグではありません。MySQL がより厳格なデータ検証へと移行した結果です。2015年にリリースされたバージョン 5.7 以降、MySQL では「厳密モード(Strict Mode)」がデフォルトで有効になりました。具体的には、以下の2つの SQL モードがこの 1067 エラーを引き起こします。

  • NO_ZERO_IN_DATE: 年は有効だが月や日がゼロである日付(例:2023-00-01)を禁止します。- NO_ZERO_DATE: 0000-00-00 00:00:00 というダミーの日付を完全に禁止します。レガシーなアプリケーションでは、これらの「ゼロ」日付をプレースホルダーとしてよく使用していました。しかし、現代の MySQL はこれらを論理的に不可能なものとして扱います。これらのデフォルト値を持つテーブルを作成しようとすると、エンジンは不正なデータがロウに混入するのを防ぐために操作をブロックします。

即効性のある解決策:セッションベース(一時的)サーバー全体の設定を変更せずに、1回限りのマイグレーションを実行したり、500MBのSQLダンプをインポートしたりする必要があるかもしれません。その場合は、現在のデータベースセッションに限り、一時的にルールを緩和することができます。メインのスクリプトを実行する前に、次のコマンドを実行してください。

-- 現在の設定を確認
SELECT @@sql_mode;

-- このセッションで日付に関する厳密モードを無効化
SET session sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

文字列から NO_ZERO_IN_DATENO_ZERO_DATE を削除することで、今回だけは「ゼロ」日付を見逃すよう MySQL に指示できます。これにより、エラーを出さずにインポートを完了させることが可能です。

恒久的な解決策:サーバー設定の変更サーバーの再起動後もこのエラーが再発しないようにするには、グローバル設定ファイルを更新する必要があります。通常、Linux では my.cnf、Windows では my.ini です。

ステップ 1: 設定ファイルの場所を確認- Ubuntu/Debian: /etc/mysql/mysql.conf.d/mysqld.cnf- CentOS/RHEL: /etc/my.cnf- Windows (XAMPP): C:\xampp\mysql\bin\my.ini### ステップ 2: SQL Mode を修正[mysqld] セクションを探します。すでに sql_mode の行が存在する場合は編集し、なければ追加してください。値に先ほどの2つの「ZERO」モードが含まれていないことを確認します。

[mysqld]
sql_mode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"

ステップ 3: サービスを再起動MySQL デーモンを再起動して変更を適用します。

# Linux ユーザーの場合
sudo systemctl restart mysql

# macOS (Homebrew) ユーザーの場合
brew services restart mysql

プロフェッショナルなアプローチ:スキーマの更新厳密モードを無効にするのは機能的な回避策ですが、最も「クリーン」な解決策ではありません。ベストプラクティスは、空の日付を適切に処理できるようにスキーマを更新することです。現代的なデータベースでは、ゼロの文字列ではなく NULL または現在の時刻を使用すべきです。

無効なデフォルト値を使用する代わりに:

-- 厳密モード(Strict Mode)では失敗します
ALTER TABLE users ADD COLUMN created_at DATETIME DEFAULT '0000-00-00 00:00:00';

次のような現代的な代替案を検討してください:

-- オプションA: NULLを許可(任意の日付項目に推奨)
ALTER TABLE users ADD COLUMN created_at DATETIME DEFAULT NULL;

-- オプションB: 現在のタイムスタンプを使用(監査ログなどに最適)
ALTER TABLE users ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP;

動作確認MySQL ターミナルにログインし、グローバルステータスをチェックして修正を確認します。

SELECT @@GLOBAL.sql_mode;

出力される文字列に NO_ZERO_DATE が含まれていなければ、CREATEALTER コマンドがスムーズに実行されるようになっているはずです。

成功のためのヒントレガシーデータには、ISO標準に準拠していない「汚れた」タイムスタンプが含まれていることがよくあります。一括インポートを試みる前に、ToolCraftのタイムスタンプコンバーターを使用して、整数のタイムスタンプが有効な日付に変換されるか確認することをお勧めします。これにより、「Invalid value」エラーのデバッグに費やす時間を大幅に節約できます。

また、アプリケーションのフレームワークも確認してください。例えば Laravel では、config/database.php でデフォルトが 'strict' => true になっています。サーバー設定を変更しても、接続フェーズでフレームワーク側が設定を上書きしてしまうことがあります。エラーが解消されない場合は、アプリケーション側の DB 設定がサーバーの新しい設定と一致しているか確認してください。

Related Error Notes