Dodając do tego, co napisał David Whittaker, utworzyłem zapytanie, które generuje kompletną instrukcję zmiany tabeli i kolumn, która konwertuje każdą tabelę. Bieganie może być dobrym pomysłem
USTAW SESJĘ group_concat_max_len = 100000;
najpierw upewnij się, że konkat grupowy nie przekracza bardzo małego limitu, jak widać tutaj .
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;
Różnica między poprzednią odpowiedzią polega na tym, że użycie utf8 zamiast ut8mb4 i użycie t1.data_type z t1.CHARACTER_MAXIMUM_LENGTH nie działa w przypadku wyliczeń. Ponadto moje zapytanie wyklucza widoki, ponieważ będą one musiały zostać zmienione osobno.
Po prostu użyłem skryptu Perla, aby zwrócić wszystkie te zmiany jako tablicę i iterowałem po nich, poprawiłem kolumny, które były zbyt długie (ogólnie były to varchar (256), kiedy dane miały zwykle tylko 20 znaków, więc była to łatwa poprawka ).
Odkryłem, że niektóre dane były uszkodzone podczas zmiany z latin1 -> utf8mb4. Wyglądało na to, że znaki latin1 zakodowane w utf8 w kolumnach zostałyby oszukane podczas konwersji. Po prostu trzymałem dane z kolumn, o których wiedziałem, że będą problemem w pamięci przed i po zmianie, porównałem je i wygenerowałem instrukcje aktualizacji, aby naprawić dane.