Mam rozwiązanie, które przekonwertuje bazy danych i tabele, uruchamiając kilka poleceń. To również konwertuje wszystkie kolumny typu varchar
, text
, tinytext
, mediumtext
, longtext
, char
. Należy również wykonać kopię zapasową bazy danych na wypadek, gdyby coś się zepsuło.
Skopiuj następujący kod do pliku o nazwie preAlterTables.sql:
use information_schema;
SELECT concat("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema, table_name;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type,"(",character_maximum_length,") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('varchar','char');
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type," CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('text','tinytext','mediumtext','longtext');
Zamień wszystkie wystąpienia „twojaDbName” na bazę danych, którą chcesz przekonwertować. Następnie uruchomić:
mysql -uroot < preAlterTables.sql | egrep '^ALTER' > alterTables.sql
Spowoduje to wygenerowanie nowego pliku alterTables.sql ze wszystkimi zapytaniami potrzebnymi do konwersji bazy danych. Uruchom następujące polecenie, aby rozpocząć konwersję:
mysql -uroot < alterTables.sql
Można to również dostosować, aby działało w wielu bazach danych, zmieniając warunek dla tabeli_schema. Na przykład table_schema like "wiki_%"
skonwertuje wszystkie bazy danych z prefiksem nazwy wiki_
. Aby przekonwertować wszystkie bazy danych, zamień warunek na table_type!='SYSTEM VIEW'
.
Problem, który może się pojawić. Miałem trochę kolumn varchar (255) w kluczach mysql. To powoduje błąd:
ERROR 1071 (42000) at line 2229: Specified key was too long; max key length is 767 bytes
Jeśli tak się stanie, możesz po prostu zmienić kolumnę na mniejszą, jak varchar (150), i ponownie uruchomić polecenie.
Uwaga : Ta odpowiedź konwertuje bazę danych na utf8mb4_unicode_ci
zamiast utf8mb4_bin
, zadane w pytaniu. Ale możesz to po prostu zastąpić.
mysql -uroot -pThatrootPassWord < alterTables.sql
działa. I jak już zauważyłeś, utf8mb4_bin jest tym, co poleca między innymi nextcloud.Użyłem następującego skryptu powłoki. Pobiera nazwę bazy danych jako parametr i konwertuje wszystkie tabele na inny zestaw znaków i zestawianie (podane przez inne parametry lub wartość domyślną zdefiniowaną w skrypcie).
źródło
Napisałbym skrypt (w Perlu lub cokolwiek innego), aby użyć schematu informacji (TABLES i COLUMNS) do przejścia przez wszystkie tabele, i wykonać MODYFIKACJĘ KOLUMNY na każdym polu CHAR / VARCHAR / TEXT. Zebrałbym wszystkie MODYFIKACJE w jedną ZMIANĘ dla każdego stołu; będzie to bardziej wydajne.
Myślę (ale nie jestem pewien), że sugestia Raihan zmienia tylko domyślną tabelę.
źródło
Wpadłem na tę sytuację; oto podejście zastosowane do konwersji mojej bazy danych:
Najpierw musisz dokonać edycji,
my.cnf
aby domyślne połączenie z bazą danych (między aplikacjami a MYSQL) było zgodne z utf8mb4_unicode_ci. Bez tych znaków, takich jak emotikony i podobne przesłane przez aplikacje, nie trafią one do tabel w prawidłowych bajtach / kodowaniu (chyba że parametry DBN CN aplikacji określają połączenie utf8mb4).Instrukcje podane tutaj .
Wykonaj następujący SQL (nie trzeba przygotowywać SQL do zmiany poszczególnych kolumn,
ALTER TABLE
instrukcje to zrobią).Przed wykonaniem poniższego kodu zamień „DbName” na rzeczywistą nazwę DB.
Zbierz i zapisz dane wyjściowe powyższego kodu SQL w pliku dot sql i uruchom je.
Jeśli pojawi się błąd podobny
#1071 - Specified key was too long; max key length is 1000 bytes.
do problematycznej nazwy tabeli, oznacza to, że klucz indeksu w pewnej kolumnie tej tabeli (która miała zostać przekonwertowana na ciąg znaków MB4) będzie bardzo duży, dlatego kolumna Varchar powinna mieć wartość <= 250, aby jej klucz indeksu będzie miał maksymalnie 1000 bajtów. Sprawdź kolumny, w których masz indeksy, a jeśli jeden z nich to varchar> 250 (najprawdopodobniej 255), toKrok 1: sprawdź dane w tej kolumnie, aby upewnić się, że maksymalny rozmiar ciągu w tej kolumnie wynosi <= 250.
Przykładowe zapytanie:
Krok 2: Jeśli maksymalna długość danych indeksowanych kolumn <= 250, zmień długość kolumny na 250. Jeśli nie jest to możliwe, usuń indeks z tej kolumny
Krok 3: Następnie ponownie uruchom zapytanie o tabelę zmian dla tej tabeli i tabela powinna teraz zostać pomyślnie przekonwertowana na utf8mb4.
Twoje zdrowie!
źródło
Napisałem ten przewodnik: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4
Z mojej pracy widziałem, że ZMIENIAJ bazę danych i tabele to za mało. Musiałem wejść do każdej tabeli i ZMIEŃ każdą z kolumn text / mediumtext / varchar.
Na szczęście udało mi się napisać skrypt wykrywający metadane baz danych MySQL, dzięki czemu mógł on przeglądać tabele i kolumny i zmieniać je automatycznie.
Długi indeks dla MySQL 5.6:
Jest jedna rzecz, do której musisz mieć uprawnienia DBA / SUPER USER: ustawienie parametrów bazy danych:
W odpowiedziach na to pytanie znajduje się instrukcja ustawiania powyższych parametrów powyżej: https://stackoverflow.com/questions/35847015/mysql-change-innodb-large-prefix
Oczywiście w moim artykule są też instrukcje, aby to zrobić.
W MySQL w wersji 5.7 lub nowszej domyślnie przedrostek innodb_large_prefix jest domyślnie WŁĄCZONY, a format pliku innodb_file_format jest domyślnie także Barracuda.
źródło
Dla osób, które mogą mieć ten problem, najlepszym rozwiązaniem jest zmodyfikowanie najpierw kolumn na typ binarny, zgodnie z poniższą tabelą:
Następnie zmodyfikuj kolumnę z powrotem do jej poprzedniego typu i pożądanym zestawem znaków.
Na przykład.:
Próbowałem na kilku stołach Latin1 i zachowałem wszystkie znaki diakrytyczne.
Możesz wyodrębnić to zapytanie dla wszystkich kolumn, które to robią:
źródło
I wykonany skrypt , który robi to mniej lub bardziej automatycznie:
źródło