Laravel迁移修改主键失败:1068多主键定义问题及原因咨询
Laravel迁移单闭包修改自增主键失败的原因
我有一张名为workflows的表,原自增主键为click_id,希望在表开头添加id字段并将其设为自增主键。
失败的迁移代码
Schema::table('workflows', function (Blueprint $table) { $table->unsignedBigInteger('click_id')->change(); $table->dropPrimary('click_id'); $table->bigIncrements('id')->first(); $table->unique(['click_id','review_id']); });
报错信息
SQLSTATE[42000]: Syntax error or access violation: 1068 Multiple primary key defined (Connection: mysql, SQL: alter table
workflowsaddidbigint unsigned not null auto_increment primary key first)
可行的解决方法
将up()方法拆分为两个独立闭包:
public function up(): void { Schema::table('workflows', function (Blueprint $table) { $table->unsignedBigInteger('click_id')->change(); $table->dropPrimary('click_id'); }); Schema::table('workflows', function (Blueprint $table) { $table->bigIncrements('id')->first(); $table->unique(['click_id','review_id']); }); } public function down(): void { Schema::table('workflows', function (Blueprint $table) { $table->dropUnique('workflows_click_id_review_id_unique'); $table->unsignedBigInteger('id')->change(); $table->dropPrimary('id'); $table->dropColumn('id'); }); DB::statement('ALTER TABLE `workflows` CHANGE `click_id` `click_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, add PRIMARY KEY (`click_id`)'); }
原因解释
问题出在Laravel Schema构建器的执行逻辑上:
- 单个
Schema::table()闭包内的所有操作,会被合并成一条ALTER TABLE SQL语句执行,而非逐条依次执行。 - 你在闭包里先调用
dropPrimary('click_id'),再调用bigIncrements('id')(该方法会自动给id添加主键约束),但这两个操作会被打包到同一条ALTER命令中。 - 对于MySQL/MariaDB来说,在同一条ALTER语句里,添加新自增主键时原主键约束还未被实际移除,就会触发"多个主键定义"的错误。
- 拆分到两个独立闭包后,每个闭包对应一条单独的ALTER TABLE语句,Laravel会按顺序执行:第一条先移除原主键并修改
click_id类型,第二条再添加新的id主键和联合唯一索引,操作顺序正确,因此不会冲突。
系统环境:Laravel 10,MariaDB 10.4.32
内容的提问来源于stack exchange,提问作者GWidgery
相关产品推荐
相关产品推荐

