除了 David Whittaker 发布的内容之外,我还创建了一个查询,该查询生成完整的表和列更改语句,该语句将转换每个表。运行可能是个好主意
设置会话 group_concat_max_len = 100000;
首先要确保您的组 concat 不会超过 here 所看到的非常小的限制。
SELECT a.table_name, concat('ALTER TABLE ', a.table_schema, '.', a.table_name, ' DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci, ',
group_concat(distinct(concat(' MODIFY ', column_name, ' ', column_type, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ', if (is_nullable = 'NO', ' NOT', ''), ' NULL ',
if (COLUMN_DEFAULT is not null, CONCAT(' DEFAULT \'', COLUMN_DEFAULT, '\''), ''), if (EXTRA != '', CONCAT(' ', EXTRA), '')))), ';') as alter_statement
FROM information_schema.columns a
INNER JOIN INFORMATION_SCHEMA.TABLES b ON a.TABLE_CATALOG = b.TABLE_CATALOG
AND a.TABLE_SCHEMA = b.TABLE_SCHEMA
AND a.TABLE_NAME = b.TABLE_NAME
AND b.table_type != 'view'
WHERE a.table_schema = ? and (collation_name = 'latin1_swedish_ci' or collation_name = 'utf8mb4_general_ci')
GROUP BY table_name;
上一个答案之间的区别在于它使用 utf8 而不是 ut8mb4 并且使用 t1.data_type 和 t1.CHARACTER_MAXIMUM_LENGTH 不适用于枚举。此外,我的查询不包括视图,因为它们必须单独更改。
我只是使用 Perl 脚本将所有这些更改作为数组返回并对其进行迭代,修复了太长的列(通常它们是 varchar(256),而数据中通常只有 20 个字符,所以这是一个简单的解决方法)。
从 latin1 -> utf8mb4 更改时,我发现一些数据已损坏。似乎列中的 utf8 编码 latin1 字符会在转换中出错。我只是在更改前后保存了我知道会在内存中出现问题的列中的数据,然后比较它们并生成更新语句来修复数据。