Como corrigir erros de "Valor incorreto da string"?

162

Depois de perceber que um aplicativo tendia a descartar emails aleatórios devido a erros incorretos no valor da string, eu fui embora e troquei muitas colunas de texto para usar o utf8charset de coluna e a coluna padrão collate ( utf8_general_ci) para aceitá-las. Isso corrigiu a maioria dos erros e fez com que o aplicativo parasse de receber erros de sql ao acessar e-mails não latinos também.

Apesar disso, alguns dos e-mails ainda estão fazendo com que o programa atinja erros incorretos no valor da string: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

A coluna de conteúdo é um MEDIUMTEXTdado que usa o conjunto de utf8caracteres da utf8_general_cicoluna e a coluna é agrupada . Não há sinalizadores que eu possa alternar nesta coluna.

Lembre-se de que não quero tocar nem olhar o código-fonte do aplicativo, a menos que seja absolutamente necessário:

  • O que está causando esse erro? (sim, eu sei que os e-mails estão cheios de lixo aleatório, mas achei que o utf8 seria bastante permissivo)
  • Como posso corrigir isso?
  • Quais são os efeitos prováveis ​​dessa correção?

Uma coisa que considerei foi mudar para um utchar8 varchar ([algum número grande]) com o sinalizador binário ativado, mas não estou familiarizado com o MySQL e não tenho idéia se essa correção faz sentido.

Brian
fonte
3
Post-mortem: a solução RichieHindle resolveu o problema e não apresentou nenhum problema adicional no período em que estava em execução. Pode ter sido um pouco complicado, mas funcionou e me permitiu evitar sujar as mãos com software de terceiros que não entendo completamente. Nesse ponto, atualizamos para uma versão mais recente do software / esquema que lida com todos esses problemas de codificação corretamente (e é novo o suficiente para ser realmente suportado), tornando o hack desnecessário.
27714 Brian

Respostas:

43

"\xE4\xC5\xCC\xC9\xD3\xD8"não é válido UTF-8. Testado usando Python:

>>> "\xE4\xC5\xCC\xC9\xD3\xD8".decode("utf-8")
...
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2: invalid data

Se você estiver procurando uma maneira de evitar erros de decodificação no banco de dados, a codificação cp1252 (também conhecida como "Windows-1252" ou "Windows Western European") é a codificação mais permissiva que existe - todo valor de byte é um ponto de código válido.

É claro que ele não entenderá mais o UTF-8 genuíno, nem qualquer outra codificação não cp1252, mas parece que você não está muito preocupado com isso?

RichieHindle
fonte
4
O que exatamente você quer dizer com: "É claro que ele não vai entender mais o UTF-8 genuíno?"
22711 Brian
5
@ Brian: Se você diz que está dando o cp1252, e você realmente dá o UTF-8 para, digamos café, isso vai interpretar mal isso café. Não irá falhar, mas não entenderá os caracteres mais importantes.
RichieHindle 22/07/2009
3
@ Richie: O banco de dados pode chamar com facilidade os dados do que quiser, mas se o código php que o agarra estiver colocando-o em uma string, isso não fará muita diferença ... será? Não vejo exatamente onde a falta de entendimento do UTF-8 está causando impacto.
22909 Brian Brian
7
@ Brian: Não, você está certo. O tempo que faria diferença seria dentro do banco de dados, por exemplo, se você usasse uma cláusula ORDER BY em seu SQL - a classificação seria complicada quando você tivesse caracteres não ASCII.
22610 RichieHindle
11
Desmarque esta resposta como solução, ocultar um erro não é a solução de nada. Remova a lâmpada de superaquecimento do seu carro e você verá.
precisa saber é o seguinte
133

Eu não sugeriria resposta Richies, porque você está estragando os dados dentro do banco de dados. Você não solucionaria o problema, mas tentaria "ocultá-lo" e não conseguir executar operações essenciais do banco de dados com os dados ocultos.

Se você encontrar esse erro, os dados que você está enviando não são codificados em UTF-8 ou sua conexão não é UTF-8. Primeiro, verifique se a fonte de dados (um arquivo, ...) realmente é UTF-8.

Em seguida, verifique sua conexão com o banco de dados, você deve fazer isso depois de conectar:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

Em seguida, verifique se as tabelas em que os dados estão armazenados têm o conjunto de caracteres utf8:

SELECT
  `tables`.`TABLE_NAME`,
  `collations`.`character_set_name`
FROM
  `information_schema`.`TABLES` AS `tables`,
  `information_schema`.`COLLATION_CHARACTER_SET_APPLICABILITY` AS `collations`
WHERE
  `tables`.`table_schema` = DATABASE()
  AND `collations`.`collation_name` = `tables`.`table_collation`
;

Por fim, verifique as configurações do banco de dados:

mysql> show variables like '%colla%';
mysql> show variables like '%charac%';

Se a origem, o transporte e o destino forem UTF-8, seu problema desapareceu;)

nico gawenda
fonte
1
@Kariem: Isso é estranho, porque essa configuração é coberta pelo comando SET NAMES, que é equivalente a chamar SET character_set_client, SET character_set_results, SET character_set_connection dev.mysql.com/doc/refman/5.1/en/charset-connection.html
Nico gawenda
2
O segundo comando deve ser SET CHARACTER SET utf8(não character_set)
Coder
6
Embora essas respostas ajudem a investigar o problema, ele não responde o que fazer para corrigi-lo. Eu vejo "latin1" em vez de "utf-8".
Vanuan 21/05
2
essa resposta é ótima para explicar o problema, mas muito ruim para detalhar a solução (que é o que o OP pediu). @nicogawenda: Quais são todas as consultas SQL a serem executadas para corrigir completamente o problema? Como corrigir todos os dados pré-existentes?
Clint Eastwood
1
"Se a origem, transporte e destino são UTF-8, o seu problema é ido;)" que era o truque para mim
suarsenegger
80

Os tipos utf-8 do MySQL não são realmente adequados utf-8 - ele usa apenas até três bytes por caractere e suporta apenas o Plano Multilíngue Básico (ou seja, sem Emoji, sem plano astral, etc.).

Se você precisar armazenar valores de planos Unicode superiores, precisará das codificações utf8mb4 .

moeffju
fonte
9
Eu acho que essa é provavelmente a melhor solução. Atualize para 5.5 e substitua utf8 por utf8mb4 nas respostas acima. Eu estava inserindo dados utf8 do Twitter que tinham emojis ou outros caracteres que precisavam de 4 bytes.
precisa saber é o seguinte
Vamos supor que não vamos atualizar para o 5.5. Como suprimimos os erros?
Utilizador
i rolada longe demais para esta mais útil resposta
handheldblender
1
10 anos desde a pergunta original. Saiba que a codificação utf8 do MySQL não é adequada para utf8. Use utf8mb4! O mesmo vale para o MariaDB. Caso contrário, você não pode ter lágrimas de alegria 😂
Liam
51

A tabela e os campos têm a codificação incorreta; no entanto, você pode convertê-los em UTF-8.

ALTER TABLE logtest CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest CHANGE title title VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci;
Jiayu Wang
fonte
1
Eu acho que essa é a resposta correta de todas. Eu tenho duas tabelas têm um formato varf utf8 cada. um deles recebeu o erro, o outro está bem. mesmo que o usuário 'update select' faça uma cópia da coluna utf8 'boa' para outra tabela, o mesmo erro ocorre. É porque as duas tabelas são criadas em versões diferentes do MySQL.
AiShiguang
Sim! Também foi uma configuração incorreta da minha tabela de banco de dados. Eu acho que essa resposta deve ser a correta. Meu problema foi que o agrupamento selecionado foi utf8_unicode_ci em vez de utf8_general_ci. Obrigado :)
jprivillaso
2
O que é esta resposta fazendo aqui, deve estar no topo
Sagun Shrestha
1
este ajuda, indica o que tentar, em vez do que pode estar errado.
Victor Di
Obrigado! Ele só me ajudou muito eu tinha mudado a formiga mesa agrupamento I thinked que deve ser ele, mas os campos ainda estavam ascii agrupamento ...
Radu
25

Resolvi esse problema hoje alterando a coluna para o tipo 'LONGBLOB', que armazena bytes não processados ​​em vez de caracteres UTF-8.

A única desvantagem de fazer isso é que você deve cuidar da codificação. Se um cliente do seu aplicativo usa codificação UTF-8 e outro usa o CP1252, seus e-mails podem ser enviados com caracteres incorretos. Para evitar isso, sempre use a mesma codificação (por exemplo, UTF-8) em todos os seus aplicativos .

Consulte esta página http://dev.mysql.com/doc/refman/5.0/en/blob.html para obter mais detalhes das diferenças entre TEXT / LONGTEXT e BLOB / LONGBLOB. Também existem muitos outros argumentos na web discutindo esses dois.

frankshaka
fonte
1
Esta solução parece ser o caminho mais fácil. Eu tentei algumas outras codificações sem sucesso.
Simeon Abolarinwa
10

Primeiro verifique se o seu default_character_set_name é utf8.

SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = "DBNAME";

Se o resultado não for utf8, você deve converter seu banco de dados. Primeiro, você deve salvar um despejo.

Para alterar o conjunto de caracteres que codifica para UTF-8 para todas as tabelas no banco de dados especificado, digite o seguinte comando na linha de comandos. Substitua DBNAME pelo nome do banco de dados:

mysql --database=DBNAME -B -N -e "SHOW TABLES" | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' | mysql --database=DBNAME

Para alterar o conjunto de caracteres que codifica para UTF-8 para o próprio banco de dados, digite o seguinte comando no prompt mysql >. Substitua DBNAME pelo nome do banco de dados:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Agora você pode tentar escrever novamente o caractere utf8 no seu banco de dados. Esta solução me ajuda quando tento fazer upload de 200000 linhas de arquivos csv no meu banco de dados.

Babacar Gningue
fonte
8

Em geral, isso acontece quando você insere seqüências de caracteres em colunas com codificação / agrupamento incompatível.

Eu recebi esse erro quando tinha TRIGGERs, que herdam o agrupamento do servidor por algum motivo. E o padrão do mysql é (pelo menos no Ubuntu) latin-1 com agrupamento sueco. Mesmo tendo o banco de dados e todas as tabelas definidas como UTF-8, ainda não havia definido my.cnf:

/etc/mysql/my.cnf:

[mysqld]
character-set-server=utf8
default-character-set=utf8

E isso deve listar todos os gatilhos com utf8- *:

select TRIGGER_SCHEMA, TRIGGER_NAME, CHARACTER_SET_CLIENT, COLLATION_CONNECTION, DATABASE_COLLATION from information_schema.TRIGGERS

E algumas das variáveis ​​listadas por isso também devem ter utf-8- * (sem latin-1 ou outra codificação):

show variables like 'char%';
Ondra Žižka
fonte
6

Embora seu agrupamento esteja definido como utf8_general_ci, suspeito que a codificação de caracteres do banco de dados, tabela ou mesmo coluna possa ser diferente.

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
Sameera Prasad Jayasinghe
fonte
5

Eu recebi um erro semelhante ( Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1). Eu tentei alterar o conjunto de caracteres da coluna para utf8mb4e depois que o erro foi alterado para 'Data too long for column 'content' at row 1'.
Acontece que o mysql me mostra um erro errado. Voltei o conjunto de caracteres da coluna para utf8e alterei o tipo da coluna para MEDIUMTEXT. Depois disso, o erro desapareceu.
Eu espero que isso ajude alguém.
By the way MariaDB no mesmo caso (eu testei o mesmo INSERT lá) apenas cortar um texto sem erro.

AVKurov
fonte
Também no MySQL eu cansei de tantas coisas, percebi que o mysql não suporta a codificação utf-8 de 4 bytes nesta versão e estava morrendo de vontade de tentar entender o que estava causando isso. Mudar o tipo aparentemente era a resposta, uma solução imediata.
Liza
4

Esse erro significa que você tem a string com codificação incorreta (por exemplo, está tentando inserir uma string codificada ISO-8859-1 na coluna codificada UTF-8) ou a coluna não suporta os dados que você está tentando inserir.

Na prática, o último problema é causado pela implementação do MySQL UTF-8 que suporta apenas caracteres UNICODE que precisam de 1 a 3 bytes quando representados no UTF-8. Veja "Valor incorreto da string" ao tentar inserir UTF-8 no MySQL via JDBC? para detalhes.

Mikko Rantalainen
fonte
2

A solução para mim ao executar esse valor incorreto de string: '\ xF8' para erro de coluna usando scriptcase era garantir que meu banco de dados esteja configurado para utf8 general ci, assim como meus agrupamentos de campos. Então, quando faço a importação de dados de um arquivo csv, carrego o csv no UE Studio e salve-o no formato utf8 e Voila! Funciona como um encanto, 29000 registros, sem erros. Anteriormente, eu estava tentando importar um CSV criado pelo Excel.

mainebrain
fonte
2

Eu tentei todas as soluções acima (que trazem pontos válidos), mas nada estava funcionando para mim.

Até descobrir que meus mapeamentos de campo da tabela MySQL em C # estavam usando um tipo incorreto: MySqlDbType.Blob . Eu mudei para MySqlDbType.Text e agora posso escrever todos os símbolos UTF8 que eu quiser!

ps Meu campo de tabela MySQL é do tipo "LongText". No entanto, quando eu gerei automaticamente os mapeamentos de campo usando o software MyGeneration, ele definiu automaticamente o tipo de campo como MySqlDbType.Blob em C #.

Curiosamente, eu tenho usado o tipo MySqlDbType.Blob com caracteres UTF8 por muitos meses sem problemas, até que um dia tentei escrever uma string com alguns caracteres específicos.

Espero que isso ajude alguém que está lutando para encontrar uma razão para o erro.

Ugnius Ramanauskas
fonte
1

Eu adicionei binário antes do nome da coluna e resolvo o erro do conjunto de caracteres.

insere nos valores da tabelaA (string binária nome do arquivo1);

Richardhe2007
fonte
1

Oi eu também tenho esse erro quando eu uso meus bancos de dados on-line do servidor godaddy eu acho que tem a versão mysql de 5.1 ou mais. mas quando eu faço do meu servidor localhost (versão 5.7), tudo bem depois que eu criei a tabela do servidor local e copiei para o servidor online usando o mysql yog, acho que o problema está no conjunto de caracteres

Captura de tela aqui

Hashain Lakshan
fonte
1

Para corrigir esse erro, atualizei meu banco de dados MySQL para utf8mb4, que suporta o conjunto completo de caracteres Unicode, seguindo este tutorial detalhado . Sugiro analisá-lo com cuidado, porque existem algumas dicas (por exemplo, as chaves de índice podem se tornar muito grandes devido às novas codificações após as quais é necessário modificar os tipos de campo).

metakermit
fonte
1

Há boas respostas aqui. Estou adicionando o meu desde que encontrei o mesmo erro, mas acabou sendo um problema completamente diferente. (Talvez na superfície o mesmo, mas uma causa raiz diferente.)

Para mim, o erro ocorreu no seguinte campo:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
private URI consulUri;

Isso acaba sendo armazenado no banco de dados como uma serialização binária da URIclasse. Isso não gerou nenhum sinalizador nos testes de unidade (usando H2) ou CI / integração (usando MariaDB4j ), explodiu em nossa configuração de produção. (Embora, uma vez que o problema tenha sido entendido, fosse fácil ver o valor errado na instância MariaDB4j; ele simplesmente não explodiu o teste.) A solução foi criar um mapeador de tipo personalizado:

package redacted;

import javax.persistence.AttributeConverter;
import java.net.URI;
import java.net.URISyntaxException;

import static java.lang.String.format;

public class UriConverter implements AttributeConverter<URI, String> {
    @Override
    public String convertToDatabaseColumn(URI attribute) {
        return attribute.toString();
    }

    @Override
    public URI convertToEntityAttribute(String field) {
        try {
            return new URI(field);
        }
        catch (URISyntaxException e) {
            throw new RuntimeException(format("could not convert database field to URI: %s", field));
        }
    }
}

Utilizado da seguinte forma:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
@Convert(converter = UriConverter.class)
private URI consulUri;

No que diz respeito ao Hibernate, parece que ele possui vários mapeadores de tipos fornecidos , incluindo for java.net.URL, mas não for java.net.URI(que é o que precisávamos aqui).

Sander Verhagen
fonte
1

No meu caso, esse problema foi resolvido alterando a codificação da coluna Mysql para 'binário' (o tipo de dados será alterado automaticamente para VARBINARY). Provavelmente não poderei filtrar ou pesquisar com essa coluna, mas não preciso disso.

WilyDen
fonte
1

Se você processar o valor com alguma função de string antes de salvar, verifique se a função pode manipular adequadamente caracteres multibyte. As funções de sequência que não podem fazer isso e estão tentando, por exemplo, truncar podem dividir um dos caracteres multibyte únicos no meio e isso pode causar situações de erro de sequência.

No PHP, por exemplo, você precisaria mudar de substrpara mb_substr.

WoodrowShigeru
fonte
0

No meu caso, primeiro encontrei um '???' no meu site, então verifico o conjunto de caracteres do Mysql, que agora é latino, então mudo para utf-8, reinicio meu projeto, recebo o mesmo erro com você e descobri que esqueci de alterar o conjunto de caracteres do banco de dados e mude para utf-8, boom, funcionou.

acoder2013
fonte
0

Eu tentei quase todos os passos mencionados aqui. Nenhum funcionou. Mariadb baixado. Funcionou. Sei que essa não é uma solução, mas isso pode ajudar alguém a identificar o problema rapidamente ou fornecer uma solução temporária.

Server version: 10.2.10-MariaDB - MariaDB Server
Protocol version: 10
Server charset: UTF-8 Unicode (utf8)
cherankrish
fonte
0

No meu caso, Incorrect string value: '\xCC\x88'...o problema era que um o-trema estava em seu estado decomposto. Essa pergunta e resposta me ajudaram a entender a diferença entre e ö. No PHP, a correção para mim foi usar a biblioteca Normalizer do PHP . Por exemplo Normalizer::normalize('o¨', Normalizer::FORM_C),.

MILÍMETROS.
fonte
-2

1 - Você deve declarar em sua conexão a propriedade de acondicionar UTF8. http://php.net/manual/en/mysqli.set-charset.php .

2 - Se você estiver usando a linha de comando mysql para executar um script, use a flag, como: Cmd: C:\wamp64\bin\mysql\mysql5.7.14\bin\mysql.exe -h localhost -u root -P 3306 --default-character-set=utf8 omega_empresa_parametros_336 < C:\wamp64\www\PontoEletronico\PE10002Corporacao\BancoDeDadosModelo\omega_empresa_parametros.sql

Roger Gusmao
fonte