列已经存在:1060在Laravel中通过迁移修改列以具有唯一索引



今天我试图在我的一个表中为一个slug创建一个字符串列。我要求列有一个唯一的索引,但表已经有了信息,所以,在创建列的那一刻,我收到了一条错误消息,通知我新列中有重复和空的值。

public function up(){
Schema::table( 'states', function( Blueprint $table ){
$table->string( 'slug', 128 )->unique();
} );
}

由于slug将包含"name"列的slugized版本,我决定分两步创建该列。首先,该列将是一个常规列,我将使用Str::slug((循环浏览所有记录,创建正确的slug值。之后,我将修改该列,在Laravel的文档中添加unique((选项:

public function up(){
Schema::table( 'states', function( Blueprint $table ){
$table->string( 'slug', 128 );
$states = State::all();
foreach( $states as $state ){
$state->slug = Str::slug( $state->name );
$state->save();
}
$table->string( 'slug', 128 )->unique()->change();
} );
}

我认为这是一个很好的解决方案,因为我不会违反数据库中的任何规则,因为所有的名称都不同。我运行了迁移,得到了一个很好的错误:

SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'slug' (SQL: alter table `states` add `slug` varchar(128) not null)

关于如何正确创建迁移,有什么想法吗?

更改行:

$table->string( 'slug', 128 )->unique()->change();

$table->unique( 'slug' );

总之:

public function up(){
Schema::table( 'states', function( Blueprint $table ){
$table->string( 'slug', 128 );
foreach( State::all() as $state ){
$state->update(['slug' => = Str::slug( $state->name )]);
}
$table->unique( 'slug' );
} );
}

请参阅https://laravel.com/docs/7.x/migrations#creating-索引。

在尝试#DigitalDrifter的答案但没有成功(我一直收到同样的错误(后,我开始怀疑问题是否是我所有的列修改都是在同一个方法function( Blueprint $table )中执行的,所以我决定将过程分为3个步骤,如下所示:

public function up(){
Schema::table( 'states', function( Blueprint $table ){
$table->string( 'slug', 128 );
} );
$states = State::all();
foreach( $states as $state ){
$state->slug = Str::slug( $state->state );
$state->save();
}
Schema::table( 'states', function( Blueprint $table ){
$table->string( 'slug', 128 )->unique()->change();
} );
}

这个版本的代码是成功的,顺便说一句,#DigitalDrifter的建议也是正确的,我用我的方法测试了$table->unique( 'slug' );,它也有效。

这里有两个问题,一个是添加重复列并应用唯一索引,另一个可能是方法Str::slug 中的冲突

在添加列或唯一索引之前,请检查它是否已经不存在

public function up() {
DB::transaction(function() {
if (!Schema::hasColumn('states', 'slug')) {
Schema::table('states', function (Blueprint $table) {
$table->string('slug', 128);
$table->unique('slug', 'unique_slug_index');
});
}
$states = State::all();
foreach( $states as $state ){
$state->slug = Str::slug( $state->name );
$state->save();
}
});
}

DB:transaction()子句会自动回滚您的迁移,如果失败。

最新更新