Добавляя к тому, что написал Дэвид Уиттакер, я создал запрос, который генерирует полный оператор таблицы и оператора 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 в столбцах дурачатся при преобразовании. Я просто держал данные из столбцов, которые, как я знал, будут проблемой в памяти до и после изменения, сравнивал их и генерировал операторы обновления для исправления данных.