web-dev-qa-db-ja.com

Laravel SQLiteを使用した移行 'デフォルト値がNULLのNOTNULL列を追加できません'

SQLiteドライバーを使用しているときにこの警告が表示されるのはなぜですか? MySQLドライバーに問題はありませんが、SQLiteがこのエラーをスローしています。

すべての移行が完了した後にシードが発生することを理解したので、私には意味がありません。データがデータベースにすでに存在する場合にのみ発生するこの問題について不平を言うのはなぜですか。

私の2つの移行は

最初の移行

  public function up() {
    Schema::create('users', function($table) {
      $table->increments('id');
      $table->string('username');
      $table->string('email');
      $table->string('password');
    });
  } 

第二次大移住

public function up() {
    Schema::table('users', function(Blueprint $table) {
        $table->date('birthday')->after('id');
        $table->string('last_name')->after('id');
        $table->string('first_name')->after('id');
    });
}

[〜#〜]エラー[〜#〜]

Exception: SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL (SQL: alter table "users" add column "birthday" date not null)
21
user391986

これはSQLiteの奇妙なことのようです。同じ問題についての Laracastフォーラムスレッドによると

テーブルを最初から追加する場合は、NOTNULLを指定できます。ただし、列を追加するときにこれを行うことはできません。 SQLiteの仕様では、これをデフォルトにする必要があるとされていますが、これは適切な選択ではありません。

SQLite ALTER TABLE docs をさらに見ると、次のことがわかりました。

NOT NULL制約が指定されている場合、列にはNULL以外のデフォルト値が必要です。

SQLiteの世界では、デフォルト値を提供しないことは、デフォルト値をNULLにする必要があると言うことと同じだと思います(このNULL不可の列にはデフォルト値がないため、値各挿入でを指定する必要があります)。

Null不可能な列を既存のテーブルに追加する必要がある場合、SQLiteは単に悪い状態のままになるようです。この列にもデフォルト値を設定しないでください。

19
JAAulde

列をnullableにしたくない場合は、Laravelにデフォルトが何であるかを知らせる必要がありますshould)。

1つのオプションは空の文字列です"" このような

public function up() {
    Schema::create('users', function($table) {
      $table->date('birthday')->after('id')->default('');
      $table->string('last_name')->after('id')->default('');
      $table->string('first_name')->after('id')->default('');

    });
  } 
7
Laurence

私がうまく使用した回避策は、使用されているデータベースドライバーを確認し、SQLiteの移行をわずかに変更することです。

例えば:

class MyMigration extends Migration
{
    public function up()
    {
        $driver = Schema::connection($this->getConnection())->getConnection()->getDriverName();

        Schema::table('invoices', function (Blueprint $table) use ($driver) {
            $table->string('stripe_invoice')->nullable()->change();

            if ('sqlite' === $driver) {
                $table->string('stripe_invoice_number')->default('');
            } else {
                $table->string('stripe_invoice_number')->after('stripe_invoice');
            }
        });
    }
}
4
StuBez

私はLaravelに精通していませんが、列の順序を指定するためのafterメソッドの使用は、具体的に[〜#〜] only [〜#〜 ]MySQL(Laravel) そして議論 (GitHub) はSQLiteでの使用の難しさを指摘しているようです。その関数: "... use after method _to specify the order of columns_"デザインは、SQLiteのドキュメントの制限に反するため互換性がない可能性があります (SQLite) 列を追加するために... :_"The new column is always appended to the end of the list of existing columns."_ ->default($value)でデフォルト値を割り当てることができるかどうかはわかりません。

4
PositiveLogic

追加する必要があります

->nullable()

ヌル値を持つ可能性のある列の場合

1
elliotanderson

この問題の別の回避策は、最初にフィールドをnull可能として作成し、後でフィールドをnull以外に変更することです。したがって、たとえばこの場合、次のようなことを行います。

public function up() {
    // Create fields first as nullable
    Schema::table('users', function(Blueprint $table) {
        $table->date('birthday')->after('id')->nullable();
        $table->string('last_name')->after('id')->nullable();
        $table->string('first_name')->after('id')->nullable();
    });

    // Either truncate existing records or assign a value to new fields
    if (true) {
        DB::table('users')->truncate();
    } else {
        DB::table('users')->update([
            'birthday' => '2019-05-01',
            'last_name' => 'last name',
            'first_name' => 'first name',
        ]);
    }

    // Change the fields to not be null
    Schema::table('users', function(Blueprint $table) {
        $table->date('birthday')->nullable(false)->change();
        $table->string('last_name')->nullable(false)->change();
        $table->string('first_name')->nullable(false)->change();
    });
}
0
shxfee