Laravel迁移修改字符集排序规则失败问题排查
Laravel迁移重命名列后排序规则被重置的问题
问题原因
Laravel的Schema::renameColumn()方法执行时,会继承当前表的默认字符集与排序规则,而非保留被重命名列(如name_new)的原有属性。这是因为Laravel构建重命名SQL时,没有完整携带原列的字符集和排序规则配置,而是依赖表的默认设置。而直接在PhpMyAdmin中重命名时,数据库会自动保留原列的所有属性,因此不会出现规则被重置的情况。
解决方案
方案一:使用原生SQL执行重命名(推荐)
绕过Laravel Schema的限制,直接用原生SQL语句完成重命名,同时显式指定字符集和排序规则:
// 1. 创建带目标排序规则的新列 Schema::table('your_table', function (Blueprint $table) { $table->string('name_new')->charset('utf8')->collation('utf8_bin')->nullable(); }); // 2. 迁移原列数据到新列 DB::table('your_table')->update(['name_new' => DB::raw('name')]); // 3. 删除原name列 Schema::table('your_table', function (Blueprint $table) { $table->dropColumn('name'); }); // 4. 用原生SQL重命名并保留属性 DB::statement('ALTER TABLE your_table CHANGE name_new name VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin NULL');
方案二:先修改表的默认排序规则
如果希望后续所有列都使用UTF8排序规则,可以先修改表的默认配置,再执行重命名:
// 1. 修改表的默认字符集和排序规则 Schema::table('your_table', function (Blueprint $table) { $table->charset = 'utf8'; $table->collation = 'utf8_bin'; }); // 2. 创建新列并迁移数据 Schema::table('your_table', function (Blueprint $table) { $table->string('name_new')->charset('utf8')->collation('utf8_bin')->nullable(); }); DB::table('your_table')->update(['name_new' => DB::raw('name')]); Schema::table('your_table', function (Blueprint $table) { $table->dropColumn('name'); }); // 3. 现在重命名会继承表的新默认规则 Schema::table('your_table', function (Blueprint $table) { $table->renameColumn('name_new', 'name'); });
注意事项
- 替换代码中的
your_table为实际表名,根据原列的类型(如string长度、是否可为空)调整SQL中的字段定义。 - 若使用Laravel 9+版本,可直接在列定义中用
->collation('utf8_bin'),无需额外指定charset(部分数据库中charset与collation关联)。
内容的提问来源于stack exchange,提问作者Styl Bandeira de Amorim Coelho
相关产品推荐
相关产品推荐

