Thêm vào những gì David Whittaker đã đăng, tôi đã tạo một truy vấn tạo ra câu lệnh thay đổi bảng và cột hoàn chỉnh sẽ chuyển đổi từng bảng. Nó có thể là một ý tưởng tốt để chạy
THIẾT LẬP nhóm_concat_max_len = 100000;
đầu tiên để đảm bảo concat nhóm của bạn không vượt quá giới hạn rất nhỏ như đã thấy ở đây .
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;
Một sự khác biệt ở đây giữa câu trả lời trước đó là nó sử dụng utf8 thay vì ut8mb4 và sử dụng t1.data_type với t1.CHARACTER_MAXIMUM_LENGTH không hoạt động cho enums. Ngoài ra, truy vấn của tôi loại trừ các lượt xem vì chúng sẽ phải thay đổi riêng.
Tôi chỉ đơn giản sử dụng tập lệnh Perl để trả về tất cả các thay đổi này dưới dạng một mảng và lặp đi lặp lại trên chúng, đã sửa các cột quá dài (nói chung chúng là varchar (256) khi dữ liệu thường chỉ có 20 ký tự trong đó để dễ khắc phục ).
Tôi tìm thấy một số dữ liệu bị hỏng khi thay đổi từ latin1 -> utf8mb4. Dường như các ký tự latin1 được mã hóa utf8 trong các cột sẽ bị biến đổi trong quá trình chuyển đổi. Tôi chỉ đơn giản giữ dữ liệu từ các cột mà tôi biết sẽ là một vấn đề trong bộ nhớ từ trước và sau khi thay đổi và so sánh chúng và tạo ra các báo cáo cập nhật để sửa dữ liệu.