我在 Latin1 有一个巨大的银行,我需要转换银行所有列的所有值。
搜索发现了一个手动执行此操作的命令。
UPDATE table SET column = CONVERT (cast (CONVERT (column USING latin1) AS BINARY) USING utf8);
但是银行有很多表和列,因此手动进行转换是不切实际的,您能帮我编写一些脚本,将该命令带到银行中的所有列吗?
NO -- 首先让我们确定完整的情况是什么。
您使用的是什么版本?如果 MySQL 5.7,请考虑使用 utf8mb4,以便可以处理 Emoji 和所有中文。如果是 5.5 或 5.6,那也是可能的,但你可能会遇到一些问题。
http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases
情况 1: 这些列当前为
CHARACTER SET latin1
和 仅包含 latin1 编码的文本。然后对每个表执行此操作:
ALTER TABLE t CONVERT TO CHARACTER SET utf8;
情况 2: 这些列当前是
CHARACTER SET latin1
但是 其中包含 utf8 编码的字符。这导致了 Mojibake 或无声的“双重编码”。该修复需要对每列进行一对更改:
情况 3(双重编码):然后,只有到那时,才需要这样做:
UPDATE tbl SET col = CONVERT(BINARY(CONVERT(col USING latin1)) USING utf8mb4);
更多讨论
字符集latin1,但其中有utf8字节;修复字符集时保留字节: 首先,假设您有 tbl.col 的声明:
col VARCHAR(111) CHARACTER SET latin1 NOT NULL
然后在不更改字节的情况下转换列:
ALTER TABLE tbl MODIFY COLUMN col VARBINARY(111) NOT NULL;
ALTER TABLE tbl MODIFY COLUMN col VARCHAR(111) CHARACTER SET utf8mb4 NOT NULL;
注意:如果从TEXT开始,请使用BLOB作为中间定义。 (这是“两步更改,如其他地方所讨论的。)(确保其他规范保持相同 - VARCHAR、NOT NULL 等)
哪种情况??
为了确定您属于哪种情况,请通过以下方式提供当前数据的小样本:
SELECT HEX(col), col FROM t WHERE ...
示例:如果
col
有
é
,并且十六进制是
E9
——那就是 latin1。如果十六进制是
C3A9
,则说明 utf8 未正确存储到 latin1 中。
C383C2A9
的十六进制表示“双重编码”。
生成 ALTER
有关如何生成ALTERs
的提示可以在here 找到。 (这不完全是你需要的,但很接近。)
然后
INSERT INTO new_table SELECT *
FROM latin_table
可能的情况:表是字符集utf8mb4,但某些列有lain1文本(从MySQL 5.7升级到8.0后)
对我有用的解决方案:
首先备份您的 BD执行前预览结果:
SELECT column_name, CONVERT(CAST(CONVERT(column_name USING LATIN1) AS BINARY) USING UTF8MB4) AS converted_column_name FROM table_name
转换:
UPDATE table_name set column_name = CONVERT(CAST(CONVERT(column_name USING LATIN1) AS BINARY) USING UTF8MB4) WHERE CONVERT(CAST(CONVERT(column_name USING LATIN1) AS BINARY) USING UTF8MB4) IS NOT NULL;
对每一列执行此操作。