我们以前的程序员在表(Mysql)中设置了错误的排序规则。他使用拉丁文归类(应为UTF8)进行设置,现在我遇到了问题。每个带有中文和日文字符的记录都变成???字符。
是否可以更改排序规则并找回字符的详细信息?
更改数据库排序规则:
ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_unicode_ci;
更改表排序规则:
ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
更改列排序规则:
ALTER TABLE <table_name> MODIFY <column_name> VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
更多信息:
这里介绍了如何更改所有数据库/表/列。运行这些查询,它们将输出将整个模式转换为utf8所需的所有后续查询。希望这会有所帮助!
-更改数据库默认排序规则
SELECT DISTINCT concat('ALTER DATABASE `', TABLE_SCHEMA, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.tables
where TABLE_SCHEMA like 'database_name';
-更改表排序规则/字符集
SELECT concat('ALTER TABLE `', TABLE_SCHEMA, '`.`', table_name, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.tables
where TABLE_SCHEMA like 'database_name';
-更改列排序规则/字符集
SELECT concat('ALTER TABLE `', t1.TABLE_SCHEMA, '`.`', t1.table_name, '` MODIFY `', t1.column_name, '` ', t1.data_type , '(' , t1.CHARACTER_MAXIMUM_LENGTH , ')' , ' CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.columns t1
where t1.TABLE_SCHEMA like 'database_name' and t1.COLLATION_NAME = 'old_charset_name';
[请注意,在Mysql中,utf8
字符集只是实际UTF8字符集的子集。为了节省一个字节的存储空间,Mysql团队决定只存储三个字节的UTF8字符,而不是完整的四个字节。这意味着某些东亚语言和表情符号未得到完全支持。要确保可以存储所有UTF8字符,请使用utf8mb4
数据类型,并在Mysql中使用utf8mb4_bin
或utf8mb4_general_ci
。
除了David Whittaker发布的内容之外,我创建了一个查询,该查询生成完整的表和将更改每个表的列alter语句。运行可能是一个好主意
SET SESSION group_concat_max_len = 100000;
首先要确保您的小组会议不会超过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字符在列中会在转换中出错。我只是简单地保存了更改前后的列中的数据,这些列我知道这将是内存中的问题,并对其进行比较并生成用于修复数据的更新语句。
here很好地描述了过程。但是,一些不适合拉丁语的字符会永远消失。 UTF-8是latin1的SUPERSET。并非相反。大多数将适合单字节空间,但任何未定义的空间将不适合(检查latin1列表-并非所有256个字符都已定义,具体取决于mysql的latin1定义)