如何在迁移中删除forms表主键id并创建复合主键?
解决删除自增主键并创建复合主键的迁移问题
这个问题我之前也碰到过,根源在于你原来的id列是自增主键,MySQL有个硬性规则:自增列必须被定义为键(主键或唯一键)。你直接删主键的话,id的自增属性还在,但它不再是键了,这就违反了规则,所以触发了1075 Incorrect table definition错误。
下面是正确的迁移步骤和代码:
核心思路
- 先移除
id列的自增属性,将其改为普通整数列(消除MySQL的规则冲突) - 删除原主键约束
- (可选)如果不需要
id列,直接删除它 - 添加
form_id和group_id组成的复合主键
完整迁移代码
public function safeUp() { // 1. 移除id列的自增属性,改为普通整数列 $this->alterColumn('forms', 'id', $this->integer(11)); // 2. 删除原主键约束(注意:Yii默认创建的主键约束名是`PRIMARY`,不是`id`) $this->dropPrimaryKey('PRIMARY', 'forms'); // 可选操作:如果不再需要id列,执行下面的删除语句 // $this->dropColumn('forms', 'id'); // 3. 添加复合主键,指定约束名为`pk_forms` $this->addPrimaryKey('pk_forms', 'forms', ['form_id', 'group_id']); } public function safeDown() { // 回滚操作:先删除复合主键 $this->dropPrimaryKey('pk_forms', 'forms'); // 可选:如果之前删除了id列,需要重新添加主键列 // $this->addColumn('forms', 'id', $this->primaryKey()); // 否则,恢复id列的自增主键属性 $this->alterColumn('forms', 'id', $this->primaryKey()); return true; }
关键注意点
- 主键约束名:Yii创建主键时,默认的约束名是
PRIMARY,而不是字段名id,所以dropPrimaryKey的第一个参数要传PRIMARY,这也是你之前代码可能踩的坑。 - 复合主键唯一性:执行迁移前,请确保
form_id和group_id的组合没有重复值,否则添加复合主键会失败(主键要求唯一)。 - 数据备份:操作表结构前建议备份数据,避免意外情况。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

