diff --git a/backend/sql/V27__fix_mojibake_history_data.sql b/backend/sql/V27__fix_mojibake_history_data.sql new file mode 100644 index 0000000..9377cda --- /dev/null +++ b/backend/sql/V27__fix_mojibake_history_data.sql @@ -0,0 +1,46 @@ +-- ===================================================================== +-- 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}'; +