Come correggere gli errori "Valore stringa errato"?


162

Dopo aver notato che un'applicazione tendeva a scartare e-mail casuali a causa di errori del valore di stringa errati, sono andato però e ho cambiato molte colonne di testo per utilizzare il utf8 set di caratteri colonna e la colonna predefinita collate ( utf8_general_ci) in modo che li accettasse. Questo risolveva la maggior parte degli errori e faceva sì che l'applicazione smettesse di ricevere errori sql anche quando colpiva email non latine.

Nonostante ciò, alcune delle e-mail stanno ancora causando al programma un errore errato nel valore di stringa: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

La colonna dei contenuti è un MEDIUMTEXTdatatybe che utilizza il utf8set di caratteri della utf8_general_cicolonna e la colonna fascicolazione. Non ci sono flag che posso attivare o disattivare in questa colonna.

Tenendo presente che non voglio toccare o nemmeno guardare il codice sorgente dell'applicazione se non assolutamente necessario:

  • Cosa sta causando questo errore? (sì, so che le e-mail sono piene di immondizia casuale, ma ho pensato che utf8 sarebbe stato abbastanza permissivo)
  • Come posso ripararlo?
  • Quali sono i probabili effetti di una simile soluzione?

Una cosa che ho considerato è stata passare a un varchar utf8 ([qualche numero grande]) con il flag binario attivato, ma non ho familiarità con MySQL e non ho idea se una tale correzione abbia senso.


3
Post mortem: la soluzione di RichieHindle ha risolto il problema e non ha introdotto ulteriori problemi durante l'esecuzione. Potrebbe essere stato un po 'un trucco, ma ha funzionato e mi ha permesso di evitare di sporcarmi le mani con software di terze parti che non capisco perfettamente. A questo punto, abbiamo aggiornato a una versione più recente del software / schema che gestisce correttamente tutti questi problemi di codifica (ed è abbastanza nuovo da essere effettivamente supportato), rendendo l'hacking non necessario.
Brian,

Risposte:


43

"\xE4\xC5\xCC\xC9\xD3\xD8"non è valido UTF-8. Testato con Python:

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

Se stai cercando un modo per evitare errori di decodifica all'interno del database, la codifica cp1252 (aka "Windows-1252" aka "Windows Western European") è la codifica più permissiva che ci sia - ogni valore di byte è un punto di codice valido.

Ovviamente non capirà più il vero UTF-8, né qualsiasi altra codifica non cp1252, ma sembra che tu non sia troppo preoccupato per quello?


4
Cosa intendi esattamente con "Naturalmente non capirà più il vero UTF-8?"
Brian,

5
@Brian: Se dici che gli stai dando cp1252, e in realtà gli dai l'UTF-8 per, diciamo café, lo interpreterà male come café. Non si schianterà, ma fraintenderà i personaggi high-bit.
RichieHindle

3
@Richie: Il database può chiamare felicemente i dati come vuole, ma se il codice php che lo cattura lo sta riempiendo in una stringa, questo non farà molta differenza ... vero? Non vedo esattamente dove la mancanza di comprensione di UTF-8 abbia un impatto.
Brian,

7
@Brian: No, hai ragione. Il tempo in cui farebbe la differenza sarebbe all'interno del database, ad esempio se si utilizzava una clausola ORDER BY nel proprio SQL - l'ordinamento sarebbe traballante in cui si trovavano caratteri non ASCII.
RichieHindle,

11
Deseleziona questa risposta come soluzione, nascondere un errore non è la soluzione di nulla. Rimuovi la lampada di surriscaldamento dalla tua auto e vedrai.
David Vartanian,

133

Non suggerirei la risposta di Richies, perché stai rovinando i dati all'interno del database. Non risolveresti il ​​problema, ma provi a "nasconderlo" e non puoi eseguire operazioni di database essenziali con i dati acquisiti.

Se si verifica questo errore, i dati che si stanno inviando non sono codificati UTF-8 oppure la connessione non è UTF-8. Innanzitutto, verifica che l'origine dati (un file, ...) sia realmente UTF-8.

Quindi, controlla la connessione al database, dovresti farlo dopo la connessione:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

Successivamente, verifica che le tabelle in cui sono archiviati i dati abbiano il set di caratteri 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`
;

Infine, controlla le impostazioni del database:

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

Se l'origine, il trasporto e la destinazione sono UTF-8, il problema è risolto;)


1
@Kariem: Questo è strano, perché questa impostazione è coperta dal comando SET NAMES, che equivale a chiamare 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
Il secondo comando dovrebbe essere SET CHARACTER SET utf8(non CHARACTER_SET)
Coder

6
Mentre questa risposta aiuta a indagare sul problema, non risponde a cosa fare per risolverlo. Vedo "latin1" invece di "utf-8".
Vanuan,

2
questa risposta è ottima per spiegare il problema, ma molto scarsa nel descrivere la soluzione (che è ciò che l'OP ha richiesto). @nicogawenda: quali sono tutte le query SQL da eseguire per risolvere completamente il problema? Come riparare tutti i dati preesistenti?
Clint Eastwood,

1
"Se la fonte, il trasporto e la destinazione sono UTF-8, il tuo problema è sparito;)" quello era il trucco per me
suarsenegger,

80

I tipi di utf-8 di MySQL non sono in realtà l'utf-8: utilizza solo fino a tre byte per carattere e supporta solo il piano multilingue di base (ovvero nessuna emoji, nessun piano astrale, ecc.).

Se è necessario memorizzare valori da piani Unicode superiori, sono necessarie le codifiche utf8mb4 .


9
Penso che questa sia probabilmente la soluzione migliore. Aggiorna a 5.5 e sostituisci utf8 con utf8mb4 nelle risposte sopra. Stavo inserendo dati utf8 da Twitter che avevano emoji o altri caratteri che avevano bisogno di 4 byte.
rmarscher,

Supponiamo che non aggiorneremo alla 5.5. Come possiamo eliminare gli errori?
Utente

ho cercato troppo a fondo per questa risposta molto utile
frullatore portatile

1
10 anni dalla domanda originale. Fai sapere che la codifica utf8 di MySQL non è corretta utf8. Usa utf8mb4! Lo stesso vale per MariaDB. Altrimenti non puoi avere lacrime di gioia 😂
Liam,

51

La tabella e i campi hanno una codifica errata; tuttavia, è possibile convertirli in 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;

1
Penso che questa sia la risposta corretta di tutte. Ho due tabelle hanno un formato varchar utf8 ciascuno. uno ha ottenuto l'errore, l'altro va bene. anche io utente 'update select' faccio una copia dalla colonna 'buona' utf8 in un'altra tabella, si verifica lo stesso errore. È perché le due tabelle sono create in diverse versioni di MySQL.
AiShiguang,

Sì! Era una configurazione errata anche dalla mia tabella del database. Penso che questa risposta dovrebbe essere quella corretta. Il mio problema era che la fascicolazione selezionata era utf8_unicode_ci invece di utf8_general_ci. Grazie :)
jprivillaso,

2
Cosa sta facendo questa risposta quaggiù, dovrebbe essere in cima
Sagun Shrestha,

1
questo aiuta, ti dice cosa provare, invece di cosa potrebbe essere sbagliato.
Victor Di

Grazie! Mi ha solo aiutato molto, avevo cambiato la formica di confronto delle tabelle, pensavo che dovesse essere così, ma i campi erano ancora ascii ...
Radu,

25

Oggi ho risolto questo problema modificando la colonna nel tipo "LONGBLOB" che memorizza i byte non elaborati anziché i caratteri UTF-8.

L'unico svantaggio nel fare questo è che devi prenderti cura della codifica da solo. Se un client dell'applicazione utilizza la codifica UTF-8 e un altro utilizza CP1252, è possibile che le e-mail vengano inviate con caratteri errati. Per evitare ciò, utilizzare sempre la stessa codifica (ad esempio UTF-8) in tutte le applicazioni .

Fare riferimento a questa pagina http://dev.mysql.com/doc/refman/5.0/en/blob.html per maggiori dettagli sulle differenze tra TEXT / LONGTEXT e BLOB / LONGBLOB. Ci sono anche molti altri argomenti sul web che parlano di questi due.


1
Questa soluzione sembra il modo più semplice di procedere. Ho provato alcune altre codifiche senza successo.
Simeon Abolarinwa,

10

Per prima cosa controlla se default_character_set_name è utf8.

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

Se il risultato non è utf8, è necessario convertire il database. All'inizio devi salvare una discarica.

Per modificare la codifica del set di caratteri in UTF-8 per tutte le tabelle nel database specificato, digitare il comando seguente nella riga di comando. Sostituisci DBNAME con il nome del database:

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

Per modificare la codifica del set di caratteri in UTF-8 per il database stesso, digitare il comando seguente al prompt mysql >. Sostituisci DBNAME con il nome del database:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Ora puoi riprovare a scrivere il carattere utf8 nel tuo database. Questa soluzione mi aiuta quando provo a caricare 200000 righe di file CSV nel mio database.


8

In generale, ciò accade quando si inseriscono stringhe in colonne con codifica / regole di confronto incompatibili.

Ho avuto questo errore quando avevo TRIGGER, che ereditano il confronto del server per qualche motivo. E il valore predefinito di mysql è (almeno su Ubuntu) latino-1 con regole di confronto svedesi. Anche se avevo il database e tutte le tabelle impostate su UTF-8, dovevo ancora impostare my.cnf:

/etc/mysql/my.cnf:

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

E questo deve elencare tutti i trigger con utf8- *:

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

E alcune delle variabili elencate da questo dovrebbero anche avere utf-8- * (nessuna codifica latin-1 o altra):

show variables like 'char%';

6

Sebbene le regole di confronto siano impostate su utf8_general_ci, sospetto che la codifica dei caratteri del database, della tabella o persino della colonna possa essere diversa.

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

5

Ho ricevuto un errore simile ( Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1). Ho provato a cambiare il set di caratteri della colonna in utf8mb4e dopo che l'errore è cambiato in 'Data too long for column 'content' at row 1'.
Si è scoperto che mysql mi mostra un errore sbagliato. Ho ripristinato il set di caratteri della colonna utf8e ho cambiato il tipo di colonna in MEDIUMTEXT. Successivamente l'errore è scomparso.
Spero che aiuti qualcuno.
A proposito MariaDB nello stesso caso (ho testato lo stesso INSERT lì) appena tagliato un testo senza errori.


Anche MySQL mi sono stancato di così tante cose, ho capito che mysql non supporta la codifica 4 byte utf-8 in questa versione e stava morendo nel tentativo di capire cosa stesse causando. La modifica del tipo apparentemente era la risposta, una soluzione immediata.
Liza,

4

Questo errore indica che hai la stringa con codifica errata (ad esempio, stai provando a inserire la stringa codificata ISO-8859-1 nella colonna codificata UTF-8) o che la colonna non supporta i dati che stai tentando di inserire.

In pratica, quest'ultimo problema è causato dall'implementazione di MySQL UTF-8 che supporta solo caratteri UNICODE che necessitano di 1-3 byte se rappresentati in UTF-8. Vedi "Valore stringa errato" quando si tenta di inserire UTF-8 in MySQL tramite JDBC? per dettagli.


2

La soluzione per me quando mi imbattevo in questo valore di stringa errato: '\ xF8' per errore di colonna che utilizza scriptcase era di essere sicuro che il mio database fosse configurato per utf8 general ci e così sono le mie regole di confronto dei campi. Quindi, quando eseguo l'importazione dei miei dati di un file CSV, carico il CSV in UE Studio, quindi lo salvo formattato come utf8 e Voila! Funziona come un incantesimo, 29000 record non ci sono errori. In precedenza stavo cercando di importare un CSV creato da Excel.


2

Ho provato tutte le soluzioni di cui sopra (che portano tutti punti validi), ma nulla funzionava per me.

Fino a quando ho scoperto che i miei mapping dei campi della tabella MySQL in C # utilizzavano un tipo errato: MySqlDbType.Blob . L'ho cambiato in MySqlDbType.Text e ora posso scrivere tutti i simboli UTF8 che voglio!

ps Il mio campo tabella MySQL è del tipo "Testo lungo". Tuttavia, quando ho generato automaticamente le mappature dei campi utilizzando il software MyGeneration, ho impostato automaticamente il tipo di campo come MySqlDbType.Blob in C #.

È interessante notare che sto usando il tipo MySqlDbType.Blob con caratteri UTF8 per molti mesi senza problemi, fino a quando un giorno ho provato a scrivere una stringa con alcuni caratteri specifici.

Spero che questo aiuti qualcuno che sta lottando per trovare una ragione per l'errore.


1

Ho aggiunto binario prima del nome della colonna e risolto l'errore del set di caratteri.

inserire nella tabella i valori (binary stringcolname1);


1

Ciao ho anche ricevuto questo errore quando uso i miei database online dal server godaddy, penso che abbia la versione mysql di 5.1 o più. ma quando lo faccio dal mio server localhost (versione 5.7) è andato bene dopo che ho creato la tabella dal server locale e copiata sul server online usando mysql yog penso che il problema sia con il set di caratteri

Screenshot qui


1

Per correggere questo errore ho aggiornato il mio database MySQL a utf8mb4 che supporta il set completo di caratteri Unicode seguendo questo tutorial dettagliato . Suggerisco di esaminarlo attentamente, perché ci sono alcuni gotcha (ad esempio le chiavi di indice possono diventare troppo grandi a causa delle nuove codifiche dopo le quali è necessario modificare i tipi di campo).


1

Ci sono buone risposte qui. Sto solo aggiungendo il mio da quando ho riscontrato lo stesso errore, ma si è rivelato un problema completamente diverso. (Forse in superficie lo stesso, ma una causa alla radice diversa.)

Per me l'errore si è verificato per il seguente campo:

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

Questo finisce per essere archiviato nel database come serializzazione binaria della URIclasse. Questo non ha sollevato alcun flag con test unitari (usando H2) o CI / test di integrazione (usando MariaDB4j ), è esploso nella nostra configurazione simile alla produzione. (Sebbene, una volta compreso il problema, sia stato abbastanza facile vedere il valore errato nell'istanza di MariaDB4j; semplicemente non ha fatto saltare il test.) La soluzione era quella di creare un mappatore di tipi personalizzato:

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));
        }
    }
}

Usato come segue:

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

Per quanto riguarda Hibernate, sembra che abbia un sacco di mappatori di tipi forniti , incluso per java.net.URL, ma non per java.net.URI(che è ciò di cui avevamo bisogno qui).


1

Nel mio caso, il problema è stato risolto modificando la codifica della colonna Mysql in "binario" (il tipo di dati verrà modificato automaticamente in VARBINARY). Probabilmente non sarò in grado di filtrare o cercare con quella colonna, ma non ne ho bisogno.


1

Se ti capita di elaborare il valore con qualche funzione stringa prima di salvare, assicurati che la funzione sia in grado di gestire correttamente i caratteri multibyte. Le funzioni di stringa che non possono farlo e, per esempio, stanno tentando di troncare potrebbero dividere uno dei singoli caratteri multibyte nel mezzo e ciò può causare tali errori di stringa.

In PHP per esempio, dovresti passare da substra mb_substr.


0

Nel mio caso, prima ho incontrato un '???' nel mio sito web, quindi controllo il set di caratteri di Mysql che ora è latino, quindi lo cambio in utf-8, quindi riavvio il mio progetto, quindi ho avuto lo stesso errore con te, poi ho scoperto che ho dimenticato di cambiare il set di caratteri del database e cambia in utf-8, boom, ha funzionato.


0

Ho provato quasi tutti i passaggi menzionati qui. Nessuno ha funzionato. Scarica mariadb. Ha funzionato. So che questa non è una soluzione, ma ciò potrebbe aiutare qualcuno a identificare rapidamente il problema o fornire una soluzione temporanea.

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

0

Nel mio caso, Incorrect string value: '\xCC\x88'...il problema era che un o-umlaut era nel suo stato decomposto. Questa domanda e risposta mi ha aiutato a capire la differenza tra e ö. In PHP, la soluzione per me era usare la libreria Normalizer di PHP . Ad es Normalizer::normalize('o¨', Normalizer::FORM_C).


-2

1 - Devi dichiarare nella tua connessione la proprietà di codificare UTF8. http://php.net/manual/en/mysqli.set-charset.php .

2 - Se si utilizza la riga di comando mysql per eseguire uno script, è necessario utilizzare il flag, come: 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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.