我使用未签名的 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();
}
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();
});
}
请注意,这仅在 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;');
}
nullable(false)
让我免于被扯掉头发,因为 nullable()
没有很好的文档记录,并且没有 notNull()
函数。
SET FOREIGN_KEY_CHECKS = 0
会出错。您可能需要使用原始查询来更改表的约束。见这里:postgresql.org/docs/current/static/sql-altertable.html
我假设您正在尝试编辑已添加数据的列,因此在不丢失数据的情况下删除列并再次添加为可空列是不可能的。我们将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;');
}
query
替换为 statement
down
函数中,SQL 语句应以 NOT NULL
结尾。 (第三个例子中的 down
函数是正确的。)
他是 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 5+,添加到 Dmitri Chebotarev 的 answer。
在需要教义/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');
}
如果您碰巧更改了列并偶然发现
'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
然后只需安装
composer require doctrine/dbal
安装 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
添加到 Dmitri Chebotarev 答案,
如果你想一次改变多列,你可以像下面那样做
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;
');
试试看:
$table->integer('user_id')->unsigned()->nullable();
->change
,仅提及 Laravel 5+
composer require doctrine/dbal
对于 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;');
}
我不得不使用 nullable(true)
Schema::table('users', function($table)
{
$table->string('name', 50)->nullable(true)->change();
});
不定期副业成功案例分享
->nullable(false)
将让您再次更改该列。