Eu tenho uma solução que irá converter bancos de dados e tabelas executando alguns comandos. Ele também converte todas as colunas do tipo varchar
, text
, tinytext
, mediumtext
, longtext
, char
. Você também deve fazer backup do seu banco de dados , caso algo ocorra.
Copie o seguinte código em um arquivo chamado 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');
Substitua todas as ocorrências de "yourDbName" pelo banco de dados que você deseja converter. Então corra:
mysql -uroot < preAlterTables.sql | egrep '^ALTER' > alterTables.sql
Isso irá gerar um novo arquivo alterTables.sql, com todas as consultas necessárias para converter o banco de dados. Execute o seguinte comando para iniciar a conversão:
mysql -uroot < alterTables.sql
Você também pode adaptar isso para executar vários bancos de dados, alterando a condição do table_schema. Por exemplo table_schema like "wiki_%"
, converterá todos os bancos de dados com o prefixo do nome wiki_
. Para converter todos os bancos de dados, substitua a condição por table_type!='SYSTEM VIEW'
.
Um problema que pode surgir. Eu tinha algumas colunas varchar (255) nas chaves do mysql. Isso causa um erro:
ERROR 1071 (42000) at line 2229: Specified key was too long; max key length is 767 bytes
Se isso acontecer, você pode simplesmente mudar a coluna para ser menor, como varchar (150), e executar novamente o comando.
Observação : esta resposta converte o banco de dados em utf8mb4_unicode_ci
vez de utf8mb4_bin
, na pergunta. Mas você pode simplesmente substituir isso.
mysql -uroot -pThatrootPassWord < alterTables.sql
funciona. E como você já observou, utf8mb4_bin é o que, entre outros, o nextcloud recomenda.Eu usei o seguinte script de shell. Ele pega o nome do banco de dados como parâmetro e converte todas as tabelas em outro conjunto de caracteres e agrupamento (fornecido por outros parâmetros ou valor padrão definido no script).
fonte
Eu escreveria um script (em Perl, ou qualquer outra coisa) para usar o information_schema (TABLES e COLUMNS) para percorrer todas as tabelas e MODIFY COLUMN em todos os campos CHAR / VARCHAR / TEXT. Eu coletaria todos os MODIFYs em um único ALTER para cada tabela; isso será mais eficiente.
Penso (mas não tenho certeza) que a sugestão de Raihan altera apenas o padrão da tabela.
fonte
Corri para esta situação; Aqui está a abordagem que eu usei para converter meu banco de dados:
Primeiro, você precisa editar
my.cnf
para tornar a conexão com o banco de dados padrão (entre aplicativos e MYSQL) compatível com utf8mb4_unicode_ci. Sem esses caracteres, como emojis e similares enviados por seus aplicativos, eles não serão exibidos em suas tabelas em bytes / codificação corretos (a menos que os parâmetros de CN CN do banco de dados do seu aplicativo especifiquem uma conexão utf8mb4).Instruções dadas aqui .
Execute o SQL a seguir (não é necessário preparar o SQL para alterar colunas individuais, as
ALTER TABLE
instruções farão isso).Antes de executar o código abaixo, substitua "DbName" pelo seu nome de banco de dados real.
Colete e salve a saída do SQL acima em um arquivo dot sql e execute-o.
Se você receber um erro como
#1071 - Specified key was too long; max key length is 1000 bytes.
o nome da tabela problemática, isso significa que a chave de índice em alguma coluna dessa tabela (que deveria ser convertida em string MB4) será muito grande, portanto a coluna Varchar deve ser <= 250 para que sua A chave de índice terá no máximo 1000 bytes. Verifique as colunas nas quais você possui índices e, se um deles for um varchar> 250 (provavelmente 255),Etapa 1: verifique os dados nessa coluna para garantir que o tamanho máximo da string nessa coluna seja <= 250.
Consulta de exemplo:
Etapa 2: se o comprimento máximo dos dados da coluna indexada for <= 250, altere o comprimento da coluna para 250. se isso não for possível, remova o índice nessa coluna
Etapa 3: execute a consulta alter table para essa tabela novamente e a tabela agora deve ser convertida em utf8mb4 com êxito.
Felicidades!
fonte
Eu escrevi este guia: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4
No meu trabalho, vi que ALTER o banco de dados e as tabelas não são suficientes. Eu tive que entrar em cada tabela e ALTERAR cada uma das colunas text / mediumtext / varchar também.
Felizmente, consegui escrever um script para detectar os metadados dos bancos de dados MySQL, para que ele pudesse percorrer as tabelas e colunas e alterá-los automaticamente.
Índice longo para MySQL 5.6:
Há uma coisa que você deve ter o privilégio DBA / SUPER USER para fazer: Definir os parâmetros do banco de dados:
Nas respostas para esta pergunta, há instruções sobre como definir esses parâmetros acima: https://stackoverflow.com/questions/35847015/mysql-change-innodb-large-prefix
Obviamente, no meu artigo, há instruções para fazer isso também.
Para o MySQL versão 5.7 ou mais recente , o innodb_large_prefix está ativado por padrão e o innodb_file_format também é o Barracuda por padrão.
fonte
Para pessoas que podem ter esse problema, a melhor solução é modificar primeiro as colunas para um tipo binário, de acordo com esta tabela:
Depois disso, modifique a coluna de volta ao seu tipo anterior e com o conjunto de caracteres desejado.
Por exemplo.:
Eu tentei em várias tabelas latin1 e manteve todos os diacríticos.
Você pode extrair esta consulta para todas as colunas fazendo isso:
fonte
Eu criei um script que faz isso mais ou menos automaticamente:
fonte