Laravel迁移更改为使列为空

我用unsigned user_id创建了一个迁移。我如何编辑user_id在一个新的迁移也使它nullable()?

Schema::create('throttle', function(Blueprint $table)
{
$table->increments('id');
// this needs to also be nullable, how should the next migration be?
$table->integer('user_id')->unsigned();
}
374055 次浏览

试一试:

$table->integer('user_id')->unsigned()->nullable();

我假设您正在尝试编辑一个已经添加了数据的列,因此在不丢失数据的情况下,删除列并作为可空列再次添加是不可能的。我们将alter现有列。

但是,Laravel的模式构建器除了重命名列外不支持修改列。 所以你需要运行原始查询来完成它们,就像这样:

function up()
{
DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

为了确保你仍然可以回滚你的迁移,我们也将做down()

function down()
{
DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

需要注意的是,由于您正在可空和不可空之间进行转换,因此您需要确保在迁移之前/之后清理数据。所以在你的迁移脚本中使用以下两种方法:

function up()
{
DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
DB::statement('UPDATE `throttle` SET `user_id` = NULL WHERE `user_id` = 0;');
}


function down()
{
DB::statement('UPDATE `throttle` SET `user_id` = 0 WHERE `user_id` IS NULL;');
DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

Laravel 5现在支持更改列;下面是官方文档中的一个例子:

Schema::table('users', function($table)
{
$table->string('name', 50)->nullable()->change();
});

来源:http://laravel.com/docs/5.0/schema#changing-columns

Laravel 4不支持修改列,因此您需要使用另一种技术,例如编写原始SQL命令。例如:

// getting Laravel App Instance
$app = app();


// getting laravel main version
$laravelVer = explode('.',$app::VERSION);


switch ($laravelVer[0]) {


// Laravel 4
case('4'):


DB::statement('ALTER TABLE `pro_categories_langs` MODIFY `name` VARCHAR(100) NULL;');
break;


// Laravel 5, or Laravel 6
default:


Schema::table('pro_categories_langs', function(Blueprint $t) {
$t->string('name', 100)->nullable()->change();
});


}

如果你碰巧改变了这些列

'Doctrine\DBAL\Driver\PDOMySql\Driver' not found

然后安装

composer require doctrine/dbal

注意,这只在Laravel 5+中是可能的。

首先,你需要教义/ dbal包:

composer require doctrine/dbal

现在在你的迁移中,你可以这样做,使列为空:

public function up()
{
Schema::table('users', function (Blueprint $table) {
// change() tells the Schema builder that we are altering a table
$table->integer('user_id')->unsigned()->nullable()->change();
});
}

您可能想知道如何恢复此操作。遗憾的是,不支持这种语法:

// Sadly does not work :'(
$table->integer('user_id')->unsigned()->change();

这是恢复迁移的正确语法:

$table->integer('user_id')->unsigned()->nullable(false)->change();

或者,如果你喜欢,你可以写一个原始查询:

public function down()
{
/* Make user_id un-nullable */
DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

再加上德米特里·切波塔列夫的回答,

如果你想一次修改多个列,你可以像下面这样做

DB::statement('
ALTER TABLE `events`
MODIFY `event_date` DATE NOT NULL,
MODIFY `event_start_time` TIME NOT NULL,
MODIFY `event_end_time` TIME NOT NULL;
');

添加到Dmitri Chebotarev回答,如Laravel 5+。

在需要教义/ dbal包之后:

composer require doctrine/dbal

然后你可以使用可空列进行迁移,如下所示:

public function up()
{
Schema::table('users', function (Blueprint $table) {
// change() tells the Schema builder that we are altering a table
$table->integer('user_id')->unsigned()->nullable()->change();
});
}

要恢复操作,请执行:

public function down()
{
/* turn off foreign key checks for a moment */
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
/* set null values to 0 first */
DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
/* alter table */
DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
/* finally turn foreign key checks back on */
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}

他是Laravel 5的完整迁移:

public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('user_id')->nullable()->change();
});
}


public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('user_id')->nullable(false)->change();
});
}

关键是,你可以通过传递false作为参数来移除nullable

对于Laravel 4.2, Unnawut的答案是最好的。但如果使用表前缀,则需要稍微更改代码。

function up()
{
$table_prefix = DB::getTablePrefix();
DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

为了确保你仍然可以回滚你的迁移,我们也将做down()

function down()
{
$table_prefix = DB::getTablePrefix();
DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

安装Composer包:

composer require doctrine/dbal

在成功安装composer包后,我们可以使用迁移命令更改数据类型和更改列名。

语法:

php artisan make:migration alter_table_[table_name]_change_[column_name] --table=[table_name]

例子:

php artisan make:migration alter_table_sessions_change_user_id --table=sessions


<?php


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


class AlterTableSessionsChangeUserId extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('sessions', function (Blueprint $table) {
$table->integer('user_id')->unsigned()->nullable()->change();
});
}


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

并运行:php artisan migrate

或刷新表以更改列名。不使用change方法。

Schema::create('throttle', function(Blueprint $table)
{
$table->increments('id');
# old code
$table->integer('user_id')->unsigned();
# new code
$table->integer('user_id')->unsigned()->nullable();
}

注意:下面的命令清除表中的数据。

php artisan migrate:refresh --path=/database/migrations/2021_09_31_050851_create_throttle_table.php

我不得不使用nullable(true)

Schema::table('users', function($table)
{
$table->string('name', 50)->nullable(true)->change();
});