列已存在:修改列以使其在Laravel中具有唯一索引并进行迁移时,为1060

问题描述 投票:1回答:3

今天,我试图在我的一张表中为一个子弹创建一个字符串列。我要求该列具有唯一索引,但是该表已经具有信息,因此,在创建该列的那一刻,我收到一条错误消息,通知我新列中的重复值和空值。

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

由于该段将包含'name'列的段化版本,所以我决定分两步创建该列。首先,该列将成为常规列,我将遍历所有记录,使用Str :: slug()创建正确的段塞值。之后,我将修改列以在Laravel's documentation之后添加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)

关于如何正确创建迁移的任何想法?

php laravel database-migration laravel-6
3个回答
1
投票

更改行:

$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-indexes


1
投票

尝试#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' );,它也有效。


0
投票

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

在添加列或唯一索引之前,检查是否还不存在

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()子句会自动回滚您的迁移(如果它失败。

© www.soinside.com 2019 - 2024. All rights reserved.