MeWrite Docs

Laravel: Unable to create table without a primary key

sql_require_primary_keyが有効な環境でLaravelマイグレーションが失敗する原因と解決策

概要

DigitalOcean Managed DatabasesやPlanetScaleなど、sql_require_primary_keyが有効なMySQL環境でLaravelマイグレーションを実行すると発生するエラー。2020年6月以降、DigitalOceanはレプリケーションのパフォーマンス問題を防ぐため、この設定を強制しています。

エラーメッセージ

SQLSTATE[HY000]: General error: 3750 Unable to create or change a table without a primary key,
when the system variable 'sql_require_primary_key' is set.
Add a primary key to the table or unset this variable to avoid this message.

原因

  1. sql_require_primary_key有効化: マネージドDB環境でPKが必須
  2. Laravelの2段階クエリ: テーブル作成とPK追加が別クエリで実行される
  3. 文字列PKの問題: $table->string('id')->primary()のような書き方で発生

問題のあるマイグレーション

1
2
3
4
5
// ❌ NG: 2つのクエリに分かれる
Schema::create('posts', function (Blueprint $table) {
    $table->string('slug');  // CREATE TABLE(PK無しでエラー)
    $table->primary('slug'); // ALTER TABLE(到達しない)
});

解決策

1. primary()をカラム定義と同時に指定(推奨)

1
2
3
4
5
6
// ✅ OK: 1つのクエリでPKも作成
Schema::create('posts', function (Blueprint $table) {
    $table->string('slug')->primary();  // CREATE TABLE with PRIMARY KEY
    $table->string('title');
    $table->timestamps();
});

2. UUIDを使う場合

1
2
3
4
5
6
// ✅ OK: uuid() + primary() を同時に
Schema::create('posts', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->string('title');
    $table->timestamps();
});

3. 標準のid()を使う(最も安全)

1
2
3
4
5
6
// ✅ OK: 標準のBigInt auto-increment
Schema::create('posts', function (Blueprint $table) {
    $table->id();  // bigIncrements('id') と同等
    $table->string('slug')->unique();
    $table->timestamps();
});

4. Laravel 7.x以降にアップグレード

Laravel 7.x以降では、この問題が修正されています。primary()の呼び出しがカラム定義と同じクエリで実行されるようになりました。

1
2
3
4
5
# Laravelバージョン確認
php artisan --version

# アップグレード
composer update laravel/framework

5. sessionsテーブルの修正

databaseセッションドライバを使う場合:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// ❌ NG: デフォルトのsessions migration
Schema::create('sessions', function (Blueprint $table) {
    $table->string('id')->unique();
    // ...
});

// ✅ OK: primary()を使う
Schema::create('sessions', function (Blueprint $table) {
    $table->string('id')->primary();  // unique() → primary()
    // ...
});

6. 一時的にsql_require_primary_keyを無効化(非推奨)

開発環境でのみ使用してください:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// マイグレーション内で一時的に無効化
public function up(): void
{
    DB::statement('SET SESSION sql_require_primary_key = 0');

    Schema::create('posts', function (Blueprint $table) {
        // ...
    });

    DB::statement('SET SESSION sql_require_primary_key = 1');
}

注意: マネージドDB環境では権限がなく実行できないことが多いです。

影響を受けるマネージドDB

プロバイダ状況
DigitalOcean2020年6月以降、強制有効
PlanetScaleデフォルト有効
AWS RDS設定可能(デフォルトは無効)
Google Cloud SQL設定可能

よくある間違い

  • $table->primary('column')を別行で書く
  • 中間テーブル(pivot)にPKを付けない
  • sessionscachejobsテーブルのPK漏れ

参考リンク

関連エラー

関連エラー

PHP の他のエラー

最終更新: 2025-12-11