You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Doctrine迁移:避免重复创建meal_moment ID0及ID替换问题

问题分析与解决方案

核心问题

  1. ID=0被自动替换为1:meal_moment表的id字段是自增主键(AUTO_INCREMENT),MySQL默认SQL_MODE下,向自增字段插入0会被视为请求生成下一个自增ID,而非直接保留0值。
  2. 部分环境迁移崩溃:原代码未检查ID=0的记录是否已存在,直接插入会触发主键重复冲突报错,导致迁移中断。

修正后的迁移代码

up 方法

public function up(Schema $schema): void
{
    // 临时设置SQL_MODE,允许向自增字段插入0值
    $this->addSql("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';");
    
    // 仅当ID=0的meal_moment不存在时才执行插入
    $this->addSql("
        INSERT INTO `meal_moment` (`id`, `name`, `code`, `ordre`, `customer_id`)
        SELECT 0, 'None', 'None', 0, 0
        WHERE NOT EXISTS (SELECT 1 FROM `meal_moment` WHERE id = 0);
    ");
    
    // 恢复默认SQL_MODE(可根据实际环境调整是否保留)
    $this->addSql("SET sql_mode = '';");
    
    // 更新order表中mealmoment_id为NULL的记录
    $this->addSql("UPDATE `order` SET mealmoment_id = 0 WHERE mealmoment_id IS NULL;");
}

down 方法(优化回滚逻辑)

public function down(Schema $schema): void
{
    // 回滚本次迁移设置的mealmoment_id=0记录(若需区分原有合法0值,可结合业务标记调整)
    $this->addSql("UPDATE `order` SET mealmoment_id = NULL WHERE mealmoment_id = 0;");
    
    // 仅当ID=0的meal_moment存在时执行删除
    $this->addSql("DELETE FROM `meal_moment` WHERE id = 0;");
}

关键说明

  • NO_AUTO_VALUE_ON_ZERO:该SQL_MODE会让MySQL将自增字段的0值视为普通数值,而非触发自增逻辑,确保ID=0能被正确插入。
  • INSERT ... SELECT + NOT EXISTS:通过判断记录是否存在避免重复插入,彻底解决主键冲突导致的迁移崩溃问题。
  • 分步骤执行SQL:拆分不同逻辑的执行步骤,提升迁移的稳定性和可调试性。

额外建议

  • 检查meal_moment表主键定义:如果业务不需要id自增,可直接移除AUTO_INCREMENT属性,从根源避免此类问题。
  • 验证回滚逻辑:在测试环境完整跑一遍迁移和回滚流程,确保不会误修改原有合法业务数据。

内容的提问来源于stack exchange,提问作者kekaaafm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:55:08