如何在将新列添加到 table 的迁移中为现有行插入与默认值不同的值

How to insert a different value for existing rows than the default in a migration that adds a new column to a table

我有一个更新 table 以添加新列的迁移:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddStringNormalizationSettingToDataSourcesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('data_sources', function (Blueprint $table) {
            $table->char('do_string_normalization', 1)->default('n')->after('vat_mode');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('data_sources', function (Blueprint $table) {
            $table->dropColumn('do_string_normalization');
        });
    }
}

这很好用,创建了该列并且所有现有行都具有值 'n'。但是,我希望默认值实际上是 'y',因此除非另有说明,否则将使用值 'y' 创建新行。

如何在创建列并更新现有行后为默认值指定不同的值?

我试过在原始列插入后添加一行:

$table->char('do_string_normalization', 1)->default('n');
$table->char('do_string_normalization', 1)->default('y')->change();

但是在运行迁移时抛出如下异常:

Unknown column type "char" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgotten to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.

谷歌搜索字符串 "Unknown column type "char" requested" 会导致 an issue on the laravel framework's tracker,建议您不能在同一迁移中修改新创建的列。我想,我可以创建另一个迁移来更改默认值。但如果可能的话,我宁愿不要只为了添加一个文件而进行两次迁移。是吗?

更新

经过进一步测试(使用多个迁移文件和两次 Schema::table() 调用)问题似乎实际上是那个学说(Laravel 使用 Symphony 的包来修改现有 tables) 不支持 char 数据类型。所以这很好用:

public function up()
{
    Schema::table('data_sources', function (Blueprint $table) {
        $table->string('do_string_normalization', 1)->default('n');
    });

    Schema::table('data_sources', function (Blueprint $table) {
        $table->string('do_string_normalization', 1)->default('y')->change();
    });
}

这样做:

public function up()
{
    Schema::table('data_sources', function (Blueprint $table) {
        $table->boolean('do_string_normalization')->default(false);
    });

    Schema::table('data_sources', function (Blueprint $table) {
        $table->boolean('do_string_normalization')->default(true)->change();
    });
}

但这会引发异常:

public function up()
{
    Schema::table('data_sources', function (Blueprint $table) {
        $table->char('do_string_normalization', 1)->default('n');
    });

    Schema::table('data_sources', function (Blueprint $table) {
        $table->char('do_string_normalization', 1)->default('y')->change();
    });
}

如果我没理解错的话,你有一个现有的 table,里面已经有很多行,你想向这个 table 添加一列。对于所有现有行,您希望将新列的值设置为 'n',对于添加到 table 的所有新行,您希望默认值为 'y'。

您可以使用原始数据库语句来实现。这是必要的,因为数据库类型之间可能存在兼容性问题,导致 Doctrine 无法支持更改 char 类型的列。

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('data_sources', function (Blueprint $table) {
            $table->char('do_string_normalization', 1)->default('n')->after('vat_mode');
        });
        
        // Note this may not be compatible with all DBs
        DB::statement('ALTER TABLE data_sources ALTER do_string_normalization SET DEFAULT "y";');
    }