Добавляя к тому, что написал Дэвид Уиттакер, я создал запрос, который генерирует полный оператор таблицы и оператора alter, который преобразует каждую таблицу.Это может быть хорошей идеей, чтобы сначала запустить
SET SESSION group_concat_max_len = 100000;
, чтобы убедиться, что ваша группа concat не выходит за очень маленький предел, как видно здесь .
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 латинские символы 1 в столбцах будут глупыми при преобразовании.Я просто держал данные из столбцов, которые, как я знал, будут проблемой в памяти до и после изменения, сравнивал их и генерировал операторы обновления для исправления данных.