问题: V26 只按 code 修好了 8 条预设品类, V25 回填的 2210/4120 备注仍是乱码; 全库体检还发现 V22 迁移写入的 platform_type 字典表 8 条名称/备注全部双重编码。 修法: 用 CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8mb4) 把 latin1 误解后的字符转回原始字节再按 utf8mb4 重新解释; 仅对 HEX 含 C2xx/C3xx 特征的值生效, 修完不再命中, 因此幂等可重复执行; platform_type 表做存在性判断, 旧结构库也能整段跑完。 验证: 生产 remaining_mojibake=0; 品类接口返回字节为正确 UTF-8(照明=e785a7e6988e); platform_type 涂鸦智能=e6b682e9b8a6e699bae883bd。
47 lines
2.3 KiB
SQL
47 lines
2.3 KiB
SQL
-- =====================================================================
|
||
-- V27 · 修复历史遗留的双重编码中文(通用回转)
|
||
-- ---------------------------------------------------------------------
|
||
-- 现象:后台「品类管理」备注、以及「平台类型」字典的名称/备注显示乱码。
|
||
--
|
||
-- 成因:V22 / V25 迁移执行时,服务器 mysql 客户端 character_set_client 为 latin1
|
||
-- (容器 C locale),UTF-8 字节被按 latin1 解读后再存入 utf8mb4 列
|
||
-- → 中文双重编码("涂鸦智能" 变成 C3A6C2B6E2809A...)。
|
||
--
|
||
-- 治本(已完成,后续迁移不会再犯):
|
||
-- - deploy-all.bat 的 mysql 调用已加 --default-character-set=utf8mb4;
|
||
-- - V25 / V26 脚本首行已加 SET NAMES utf8mb4。
|
||
-- 本脚本负责把历史数据修回来。
|
||
--
|
||
-- 修法:把 latin1 误解后的字符按 latin1 转回原始字节,再按 utf8mb4 重新解释:
|
||
-- CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8mb4)
|
||
-- 幂等:仅对仍含双重编码特征(HEX 含 C2xx / C3xx)的值生效,修完不再命中。
|
||
--
|
||
-- 无存储过程、无 DELIMITER;幂等可重复执行。
|
||
-- =====================================================================
|
||
|
||
SET NAMES utf8mb4;
|
||
|
||
-- ---------- 1) 平台类型字典(V22 写入;表可能不存在,做存在性判断) ----------
|
||
SET @has_pt = (SELECT COUNT(*) FROM information_schema.TABLES
|
||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'platform_type');
|
||
SET @s = IF(@has_pt > 0,
|
||
'UPDATE platform_type
|
||
SET name = CONVERT(CAST(CONVERT(name USING latin1) AS BINARY) USING utf8mb4),
|
||
remark = CONVERT(CAST(CONVERT(remark USING latin1) AS BINARY) USING utf8mb4),
|
||
update_time = NOW()
|
||
WHERE deleted = 0
|
||
AND (HEX(IFNULL(name, '''')) REGEXP ''C[23][0-9A-F]{2}''
|
||
OR HEX(IFNULL(remark, '''')) REGEXP ''C[23][0-9A-F]{2}'')',
|
||
'SELECT ''platform_type table not found, skipped'' AS info');
|
||
PREPARE stmt FROM @s;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- ---------- 2) 品类字典备注(V25 回填历史品类时写入) ----------
|
||
UPDATE product_category
|
||
SET remark = CONVERT(CAST(CONVERT(remark USING latin1) AS BINARY) USING utf8mb4),
|
||
update_time = NOW()
|
||
WHERE deleted = 0
|
||
AND HEX(IFNULL(remark, '')) REGEXP 'C[23][0-9A-F]{2}';
|
||
|