Laravel migration with SQLite 'Cannot add a NOT NULL column with default value NULL'

前端 未结 8 693
隐瞒了意图╮
隐瞒了意图╮ 2020-12-05 23:50

Why am I getting this warning when using the SQLite driver? I have no problems with the MySQL driver but SQLite is throwing this error.

It does not make sense to me

相关标签:
8条回答
  • 2020-12-05 23:58

    If you don't want the column to be nullable - then you need to let Laravel know what the default should be.

    One option is an empty string "" like this

    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('');
    
        });
      } 
    
    0 讨论(0)
  • 2020-12-05 23:59

    It looks like this is a SQLite oddity. According to a Laracast forum thread about the same issue:

    When adding a table from scratch, you can specify NOT NULL. However, you can't do this when adding a column. SQLite's specification says you have to have a default for this, which is a poor choice.

    Looking further to the SQLite ALTER TABLE docs, I found:

    If a NOT NULL constraint is specified, then the column must have a default value other than NULL.

    I suppose in the world of SQLite, not providing a default value is the same thing as saying the default value should be NULL (as opposed to meaning there is no default value for this non-nullable column, so a value must be provided for it on each insert).

    It seems SQLite simply leaves you in a bad state if you need to add a non-nullable column to an existing table, which column should also not have a default value.

    0 讨论(0)
  • 2020-12-06 00:01

    you have to add

    ->nullable()
    

    for the columns that may have a null value

    0 讨论(0)
  • A workaround I've used successfully is to check which database driver is being used and slightly modify the migration for SQLite.

    For example:

    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');
                }
            });
        }
    }
    
    0 讨论(0)
  • 2020-12-06 00:15

    Another work around for this issue is to first create the fields as nullable and then later change the fields to be not null. So for example in this case we will do something like the following:

    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 讨论(0)
  • 2020-12-06 00:16

    I did as people explained and it worked, just make your foreign keys nullables in your migration

    public function up()
    {
        Schema::table('products', function (Blueprint $table) {
            $table->foreignId('category_id')
                ->nullable()
                ->constrained();
        });
    }
    
    0 讨论(0)
提交回复
热议问题