Wie behebe ich Fehler "Falscher Zeichenfolgenwert"?

162

Nachdem ich festgestellt hatte, dass eine Anwendung aufgrund falscher Zeichenfolgenfehler dazu neigte, zufällige E-Mails zu verwerfen, wechselte ich viele Textspalten, um den utf8Spaltenzeichensatz und die Standardspalte collate ( utf8_general_ci) zu verwenden, damit sie akzeptiert werden. Dies behebt die meisten Fehler und führt dazu, dass die Anwendung keine SQL-Fehler mehr erhält, wenn auch nicht-lateinamerikanische E-Mails empfangen werden.

Trotzdem führen einige E-Mails immer noch dazu, dass das Programm falsche Fehler bei den Zeichenfolgenwerten trifft: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

Die Inhaltsspalte ist eine MEDIUMTEXTDatenbank, die den utf8Spaltenzeichensatz und die utf8_general_ciSpaltenkollatierung verwendet. In dieser Spalte gibt es keine Flags, die ich umschalten kann.

Denken Sie daran, dass ich den Quellcode der Anwendung nicht berühren oder gar ansehen möchte, es sei denn, dies ist unbedingt erforderlich:

  • Was verursacht diesen Fehler? (Ja, ich weiß, dass die E-Mails voller zufälliger Abfälle sind, aber ich dachte, utf8 wäre ziemlich freizügig.)
  • Wie kann ich es reparieren?
  • Was sind die wahrscheinlichen Auswirkungen eines solchen Fixes?

Eine Sache, die ich in Betracht gezogen habe, war der Wechsel zu einem utf8-Varchar ([eine große Zahl]) mit aktiviertem Binärflag, aber ich bin mit MySQL eher unbekannt und habe keine Ahnung, ob eine solche Korrektur sinnvoll ist.

Brian
quelle
3
Post-mortem: Die Lösung von RichieHindle löste das Problem und führte in der Laufzeit keine zusätzlichen Probleme ein. Es war vielleicht ein bisschen ein Hack, aber es hat funktioniert und es mir ermöglicht, meine Hände nicht mit Software von Drittanbietern schmutzig zu machen, die ich nicht vollständig verstehe. Zu diesem Zeitpunkt haben wir auf eine neuere Version der Software / des Schemas aktualisiert, die alle diese Codierungsprobleme ordnungsgemäß behandelt (und neu genug ist, dass sie tatsächlich unterstützt wird), wodurch der Hack unnötig wird.
Brian

Antworten:

43

"\xE4\xC5\xCC\xC9\xD3\xD8"ist nicht gültig UTF-8. Getestet mit Python:

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

Wenn Sie nach einer Möglichkeit suchen, Dekodierungsfehler in der Datenbank zu vermeiden, ist die cp1252-Codierung (auch bekannt als "Windows-1252" oder "Windows Western European") die zulässigste Codierung, die es gibt - jeder Bytewert ist ein gültiger Codepunkt.

Natürlich wird es weder echtes UTF-8 noch andere Nicht-CP1252-Codierungen mehr verstehen, aber es hört sich so an, als wären Sie darüber nicht allzu besorgt?

RichieHindle
quelle
4
Was genau meinst du mit "Natürlich wird es echtes UTF-8 nicht mehr verstehen?"
Brian
5
@Brian: Wenn du es sagst, gibst du es cp1252 und du gibst ihm tatsächlich das UTF-8, zum Beispiel café, es wird das falsch interpretieren als café. Es wird nicht abstürzen, aber es wird die High-Bit-Zeichen falsch verstehen.
RichieHindle
3
@Richie: Die Datenbank kann die Daten gerne aufrufen, was immer sie wollen, aber wenn der PHP-Code, der sie erfasst, sie in eine Zeichenfolge stopft, macht das keinen großen Unterschied ... oder? Ich sehe nicht genau, wo sich das mangelnde Verständnis von UTF-8 auswirkt.
Brian
7
@ Brian: Nein, du hast recht. Die Zeit, die einen Unterschied machen würde, würde innerhalb der Datenbank liegen, wenn Sie beispielsweise eine ORDER BY-Klausel in Ihrem SQL verwenden würden - die Sortierung wäre wackelig, wenn Sie Nicht-ASCII-Zeichen hätten.
RichieHindle
11
Bitte deaktivieren Sie diese Antwort als Lösung. Das Ausblenden eines Fehlers ist keine Lösung. Entfernen Sie die Überhitzungslampe von Ihrem Auto und Sie werden sehen.
David Vartanian
133

Ich würde Richies Antwort nicht vorschlagen, weil Sie die Daten in der Datenbank vermasseln. Sie würden Ihr Problem nicht beheben, sondern versuchen, es zu "verbergen" und nicht in der Lage zu sein, wesentliche Datenbankoperationen mit den beschissenen Daten auszuführen.

Wenn Sie auf diesen Fehler stoßen, sind entweder die von Ihnen gesendeten Daten nicht UTF-8-codiert oder Ihre Verbindung ist nicht UTF-8. Stellen Sie zunächst sicher, dass die Datenquelle (eine Datei, ...) wirklich UTF-8 ist.

Überprüfen Sie dann Ihre Datenbankverbindung. Führen Sie dies nach dem Herstellen der Verbindung aus:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

Stellen Sie als Nächstes sicher, dass die Tabellen, in denen die Daten gespeichert sind, den Zeichensatz utf8 haben:

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`
;

Überprüfen Sie zuletzt Ihre Datenbankeinstellungen:

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

Wenn Quelle, Transport und Ziel UTF-8 sind, ist Ihr Problem weg;)

nico gawenda
quelle
1
@Kariem: Dies ist seltsam, da diese Einstellung durch den Befehl SET NAMES abgedeckt wird, der dem Aufruf von SET charakter_set_client, SET charakter_set_results, SET charakter_set_connection dev.mysql.com/doc/refman/5.1/de/charset-connection.html entspricht
Nico Gawenda
2
Der zweite Befehl sollte sein SET CHARACTER SET utf8(nicht CHARACTER_SET)
Coder
6
Diese Antworten helfen zwar bei der Untersuchung des Problems, beantworten jedoch nicht, was zu tun ist, um das Problem zu beheben. Ich sehe "latin1" anstelle von "utf-8".
Vanuan
2
Diese Antwort ist gut darin, das Problem zu erklären, aber sehr schlecht darin, die Lösung zu beschreiben (was OP verlangt hat). @nicogawenda: Welche SQL-Abfragen müssen ausgeführt werden, um das Problem vollständig zu beheben? Wie kann ich alle bereits vorhandenen Daten reparieren?
Clint Eastwood
1
"Wenn Quelle, Transport und Ziel UTF-8 sind, ist Ihr Problem weg;)" das war der Trick für mich
suarsenegger
80

Die utf-8-Typen von MySQL sind eigentlich keine richtigen utf-8-Typen - sie verwenden nur bis zu drei Bytes pro Zeichen und unterstützen nur die mehrsprachige Grundebene (dh kein Emoji, keine Astralebene usw.).

Wenn Sie Werte aus höheren Unicode-Ebenen speichern müssen, benötigen Sie die utf8mb4-Codierungen .

Moeffju
quelle
9
Ich denke, das ist wahrscheinlich die beste Lösung. Aktualisieren Sie auf 5.5 und ersetzen Sie utf8 in den obigen Antworten durch utf8mb4. Ich habe utf8-Daten von Twitter eingefügt, die Emojis oder andere Zeichen hatten, die 4 Bytes benötigten.
Rmarscher
Nehmen wir an, wir werden kein Upgrade auf 5.5 durchführen. Wie unterdrücken wir die Fehler?
Benutzer
Ich habe viel zu weit gescrollt für diese nützlichste Antwort
Handheldblender
1
10 Jahre seit der ursprünglichen Frage. Lassen Sie es wissen, dass die utf8-Codierung von MySQL nicht die richtige utf8 ist. Verwenden Sie utf8mb4! Gleiches gilt für MariaDB. Sonst kann man keine Freudentränen haben 😂
Liam
51

Die Tabelle und die Felder haben die falsche Codierung. Sie können sie jedoch in UTF-8 konvertieren.

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
quelle
1
Ich denke, dies ist die richtige Antwort von allen. Ich habe zwei Tabellen, die jeweils ein utf8-Varchar-Format haben. Einer hat den Fehler bekommen, der andere ist in Ordnung. Selbst wenn der Benutzer 'update select' eine Kopie aus der Spalte 'good' utf8 in eine andere Tabelle erstellt, tritt der gleiche Fehler auf. Dies liegt daran, dass die beiden Tabellen in unterschiedlichen Versionen von MySQL erstellt werden.
AiShiguang
Ja! Es war auch eine Fehlkonfiguration aus meiner Datenbanktabelle. Ich denke, diese Antwort sollte die richtige sein. Mein Problem war, dass die ausgewählte Sortierung utf8_unicode_ci anstelle von utf8_general_ci war. Danke :)
jprivillaso
2
Was ist diese Antwort hier unten, sollte oben sein
Sagun Shrestha
1
Dieser hilft, er sagt dir, was du versuchen sollst, anstatt was falsch sein könnte.
Victor Di
Danke dir! Es hat mir nur sehr geholfen, dass ich die Tabellensortierung geändert hatte und ich dachte, das sollte es sein, aber die Felder waren immer noch ASCII-Kollatierung ...
Radu
25

Ich habe dieses Problem heute gelöst, indem ich die Spalte in den Typ 'LONGBLOB' geändert habe, in dem Rohbytes anstelle von UTF-8-Zeichen gespeichert sind.

Der einzige Nachteil dabei ist, dass Sie sich selbst um die Codierung kümmern müssen. Wenn ein Client Ihrer Anwendung die UTF-8-Codierung und ein anderer CP1252 verwendet, werden Ihre E-Mails möglicherweise mit falschen Zeichen gesendet. Um dies zu vermeiden, verwenden Sie für alle Ihre Anwendungen immer dieselbe Codierung (z. B. UTF-8) .

Weitere Informationen zu den Unterschieden zwischen TEXT / LONGTEXT und BLOB / LONGBLOB finden Sie auf dieser Seite unter http://dev.mysql.com/doc/refman/5.0/en/blob.html . Es gibt auch viele andere Argumente im Internet, die diese beiden diskutieren.

Frankshaka
quelle
1
Diese Lösung scheint der einfachste Weg zu sein. Ich habe einige andere Codierungen ohne Erfolg ausprobiert.
Simeon Abolarinwa
10

Überprüfen Sie zunächst, ob Ihr Standardcharakter_set_name utf8 ist.

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

Wenn das Ergebnis nicht utf8 ist, müssen Sie Ihre Datenbank konvertieren. Zuerst müssen Sie einen Dump speichern.

Geben Sie den folgenden Befehl in die Befehlszeile ein, um die Zeichensatzcodierung für alle Tabellen in der angegebenen Datenbank in UTF-8 zu ändern. Ersetzen Sie DBNAME durch den Datenbanknamen:

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

Geben Sie den folgenden Befehl an der Eingabeaufforderung mysql > ein, um die Zeichensatzcodierung für die Datenbank selbst in UTF-8 zu ändern . Ersetzen Sie DBNAME durch den Datenbanknamen:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Sie können jetzt erneut versuchen, utf8-Zeichen in Ihre Datenbank zu schreiben. Diese Lösung hilft mir, wenn ich versuche, eine 200000-Zeile einer CSV-Datei in meine Datenbank hochzuladen.

Babacar Gningue
quelle
8

Im Allgemeinen geschieht dies, wenn Sie Zeichenfolgen in Spalten mit inkompatibler Codierung / Sortierung einfügen.

Ich habe diesen Fehler erhalten, als ich TRIGGERs hatte, die aus irgendeinem Grund die Sortierung des Servers erben. Und MySQLs Standard ist (zumindest unter Ubuntu) Latin-1 mit schwedischer Sortierung. Obwohl ich die Datenbank und alle Tabellen auf UTF-8 eingestellt hatte, musste ich noch Folgendes festlegen my.cnf:

/etc/mysql/my.cnf:

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

Und dies muss alle Trigger mit utf8- * auflisten:

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

Und einige der hier aufgeführten Variablen sollten auch utf-8- * haben (kein Latin-1 oder eine andere Codierung):

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

Obwohl Ihre Sortierung auf utf8_general_ci festgelegt ist, vermute ich, dass die Zeichenkodierung der Datenbank, Tabelle oder sogar Spalte unterschiedlich sein kann.

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

Ich habe einen ähnlichen Fehler ( Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1). Ich habe versucht, den Zeichensatz der Spalte in zu ändern, utf8mb4und danach hat sich der Fehler in geändert 'Data too long for column 'content' at row 1'.
Es stellte sich heraus, dass MySQL mir einen falschen Fehler anzeigt. Ich habe den Zeichensatz der Spalte auf zurückgesetzt utf8und den Spaltentyp auf geändert MEDIUMTEXT. Danach verschwand der Fehler.
Ich hoffe es hilft jemandem.
Übrigens, MariaDB hat im selben Fall (ich habe dort das gleiche INSERT getestet) einfach einen Text ohne Fehler geschnitten.

AVKurov
quelle
Auch MySQL Ich habe so viele Dinge satt, festgestellt, dass MySQL in dieser Version kein 4-Byte-Utf-8-Uncoding unterstützt, und wollte unbedingt verstehen, was dies verursacht. Anscheinend war es die Antwort, den Typ zu ändern, eine sofortige Lösung.
Liza
4

Dieser Fehler bedeutet, dass Sie entweder eine Zeichenfolge mit falscher Codierung haben (z. B. versuchen Sie, eine ISO-8859-1-codierte Zeichenfolge in eine UTF-8-codierte Spalte einzugeben) oder die Spalte die Daten, die Sie eingeben möchten, nicht unterstützt.

In der Praxis wird das letztere Problem durch die Implementierung von MySQL UTF-8 verursacht, die nur UNICODE-Zeichen unterstützt, die 1-3 Byte benötigen, wenn sie in UTF-8 dargestellt werden. Siehe "Falscher Zeichenfolgenwert" beim Versuch, UTF-8 über JDBC in MySQL einzufügen? für Details.

Mikko Rantalainen
quelle
2

Die Lösung für mich, wenn ich auf diesen falschen Zeichenfolgenwert stoße: '\ xF8' für Spaltenfehler mit scriptcase, bestand darin, sicherzustellen, dass meine Datenbank für utf8 general ci eingerichtet ist, ebenso wie meine Feldkollatierungen. Wenn ich dann einen Datenimport einer CSV-Datei durchführe, lade ich die CSV in UE Studio und speichere sie formatiert als utf8 und Voila! Es funktioniert wie ein Zauber, 29000 Datensätze enthalten keine Fehler. Zuvor habe ich versucht, eine von Excel erstellte CSV zu importieren.

Mainebrain
quelle
2

Ich habe alle oben genannten Lösungen ausprobiert (die alle gültige Punkte bringen), aber für mich hat nichts funktioniert.

Bis ich feststellte, dass meine MySQL-Tabellenfeldzuordnungen in C # einen falschen Typ verwendeten: MySqlDbType.Blob . Ich habe es in MySqlDbType.Text geändert und jetzt kann ich alle gewünschten UTF8-Symbole schreiben!

ps Mein MySQL-Tabellenfeld ist vom Typ "LongText". Wenn ich jedoch die Feldzuordnungen mit der MyGeneration-Software automatisch generierte, wurde der Feldtyp in C # automatisch als MySqlDbType.Blob festgelegt.

Interessanterweise verwende ich den MySqlDbType.Blob-Typ seit vielen Monaten ohne Probleme mit UTF8-Zeichen, bis ich eines Tages versuchte, eine Zeichenfolge mit bestimmten Zeichen zu schreiben.

Ich hoffe, dies hilft jemandem, der Schwierigkeiten hat, einen Grund für den Fehler zu finden.

Ugnius Ramanauskas
quelle
1

Ich habe vor dem Spaltennamen eine Binärdatei hinzugefügt und den Zeichensatzfehler behoben.

in tableA-Werte einfügen (binärer stringcolname1);

Richardhe2007
quelle
1

Hallo, ich habe diesen Fehler auch erhalten, wenn ich meine Online-Datenbanken vom Godaddy-Server verwende. Ich denke, es hat die MySQL-Version 5.1 oder höher. aber wenn ich es von meinem localhost-Server (Version 5.7) mache, war es in Ordnung, danach habe ich die Tabelle vom lokalen Server erstellt und mit mysql yog auf den Online-Server kopiert. Ich denke, das Problem liegt im Zeichensatz

Screenshot hier

Hashain Lakshan
quelle
1

Um diesen Fehler zu beheben, habe ich meine MySQL-Datenbank auf utf8mb4 aktualisiert, das den vollständigen Unicode-Zeichensatz unterstützt, indem ich diesem ausführlichen Tutorial folge . Ich empfehle, es sorgfältig durchzugehen, da es einige Fallstricke gibt (z. B. können die Indexschlüssel aufgrund der neuen Codierungen, nach denen Sie die Feldtypen ändern müssen, zu groß werden).

Metakermit
quelle
1

Hier gibt es gute Antworten. Ich füge nur meine hinzu, da ich auf den gleichen Fehler gestoßen bin, aber es stellte sich heraus, dass es ein völlig anderes Problem war. (Vielleicht an der Oberfläche gleich, aber eine andere Grundursache.)

Bei mir ist der Fehler für das folgende Feld aufgetreten:

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

Dies wird in der Datenbank als binäre Serialisierung der gespeichert URI Klasse . Dies hat bei Unit-Tests (mit H2) oder CI / Integrationstests (mit MariaDB4j ) keine Flags ausgelöst , sondern in unserem produktionsähnlichen Setup explodiert . (Sobald das Problem verstanden wurde, war es leicht genug, den falschen Wert in der MariaDB4j-Instanz zu erkennen. Der Test wurde einfach nicht in die Luft gesprengt.) Die Lösung bestand darin, einen benutzerdefinierten Typ-Mapper zu erstellen:

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

Wird wie folgt verwendet:

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

Was Hibernate betrifft, so scheint es, dass es eine Reihe von bereitgestellten Typ-Mappern gibt , einschließlich für java.net.URL, aber nicht für java.net.URI(was wir hier brauchten).

Sander Verhagen
quelle
1

Wenn Sie den Wert vor dem Speichern mit einer Zeichenfolgenfunktion verarbeiten, stellen Sie sicher, dass die Funktion Multibyte-Zeichen ordnungsgemäß verarbeiten kann. Zeichenfolgenfunktionen, die dies nicht können und beispielsweise versuchen, abzuschneiden, teilen möglicherweise eines der einzelnen Multibyte-Zeichen in der Mitte auf, was zu solchen Zeichenfolgenfehlersituationen führen kann.

In PHP zum Beispiel müßten Sie aus wechseln substrzu mb_substr.

WoodrowShigeru
quelle
0

In meinem Fall habe ich zuerst ein '???' Auf meiner Website überprüfe ich dann den lateinischen Zeichensatz von MySQL, ändere ihn in utf-8, starte mein Projekt neu, habe dann den gleichen Fehler bei Ihnen und habe festgestellt, dass ich vergessen habe, den Zeichensatz der Datenbank zu ändern und in utf-8 wechseln, boom, es hat funktioniert.

acoder2013
quelle
0

Ich habe fast alle hier genannten Schritte ausprobiert. Keiner hat funktioniert. Mariadb heruntergeladen. Es funktionierte. Ich weiß, dass dies keine Lösung ist, aber dies könnte jemandem helfen, das Problem schnell zu identifizieren oder eine vorübergehende Lösung zu finden.

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

In meinem Fall wurde dieses Problem gelöst, indem die MySQL-Spaltencodierung in 'binär' geändert wurde (der Datentyp wird automatisch in VARBINARY geändert). Wahrscheinlich kann ich mit dieser Spalte nicht filtern oder suchen, aber das brauche ich nicht.

WilyDen
quelle
0

In meinem Fall bestand Incorrect string value: '\xCC\x88'...das Problem darin, dass sich ein O-Umlaut in seinem zerlegten Zustand befand. Diese Frage und Antwort half mir, den Unterschied zwischen und zu verstehen ö. In PHP bestand die Lösung für mich darin, die Normalizer-Bibliothek von PHP zu verwenden . ZB , Normalizer::normalize('o¨', Normalizer::FORM_C).

MM.
quelle
-2

1 - Sie müssen in Ihrer Verbindung die Eigenschaft angeben, UTF8 einzuschließen. http://php.net/manual/en/mysqli.set-charset.php .

2 - Wenn Sie die MySQL-Befehlszeile verwenden, um ein Skript auszuführen, müssen Sie das Flag wie folgt verwenden: 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
quelle