Как исправить ошибки «Неверное строковое значение»?

162

Заметив, что приложение склонно отбрасывать случайные электронные письма из-за неправильных ошибок строковых значений, я пошел и переключил многие текстовые столбцы, чтобы использовать utf8набор символов столбца и столбец по умолчанию collate ( utf8_general_ci), чтобы он принимал их. Это исправило большинство ошибок и заставило приложение перестать получать sql-ошибки, когда оно попадало и на нелатинские электронные письма.

Несмотря на это, некоторые электронные письма все еще приводят к тому, что программа ошибается ошибочными строковыми значениями: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

Столбец содержимого представляет собой MEDIUMTEXTтип данных, который использует набор utf8символов utf8_general_ciстолбца и сопоставление столбца. В этом столбце нет флагов, которые я могу переключить.

Помня о том, что я не хочу трогать или даже смотреть на исходный код приложения без крайней необходимости:

  • Что вызывает эту ошибку? (да, я знаю, что письма полны случайного мусора, но я подумал, что utf8 будет довольно разрешительным)
  • Как я могу это исправить?
  • Каковы возможные последствия такого исправления?

Одна вещь, которую я рассмотрел, это переключение на utf8 varchar ([какое-то большое количество]) с включенным двоичным флагом, но я довольно незнаком с MySQL и не знаю, имеет ли такое исправление смысл.

Брайан
источник
3
Посмертно: решение RichieHindle решило проблему и не добавило никаких дополнительных проблем во время работы. Возможно, это было что-то вроде взлома, но это сработало и позволило мне не испачкать руки сторонним программным обеспечением, которое я до конца не понимаю. К этому моменту мы обновились до более новой версии программного обеспечения / схемы, которая корректно обрабатывает все эти проблемы кодирования (и является достаточно новой, чтобы фактически поддерживаться), что делает ненужным хакерство.
Брайан

Ответы:

43

"\xE4\xC5\xCC\xC9\xD3\xD8"недействителен UTF-8. Протестировано с использованием Python:

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

Если вы ищете способ избежать ошибок декодирования в базе данных, кодировка cp1252 (также называемая «Windows-1252» или «Западноевропейская Windows») является наиболее допустимой кодировкой из всех существующих - каждое значение байта является допустимой кодовой точкой.

Конечно, он больше не поймет ни подлинный UTF-8, ни какую-либо другую кодировку, отличную от cp1252, но, похоже, вас это не слишком беспокоит?

RichieHindle
источник
4
Что именно вы подразумеваете под «Конечно, он больше не будет понимать подлинный UTF-8?»
Брайан
5
@ Брайан: Если вы скажете, что вы даете ему cp1252, и вы на самом деле даете ему UTF-8 для, скажем café, это будет неверно истолковано как café. Он не рухнет, но неправильно поймет символы старшего разряда.
RichieHindle
3
@Richie: База данных может с радостью вызывать данные как угодно, но если код php, который захватывает их, вставляет их в строку, это не будет иметь большого значения ... не так ли? Я не знаю точно, где недостаток понимания UTF-8 оказывает влияние.
Брайан
7
@ Брайан: Нет, ты прав. Время, которое будет иметь значение, будет в пределах базы данных, например, если вы используете предложение ORDER BY в своем SQL - сортировка будет неудачной, если у вас есть символы не ASCII.
RichieHindle
11
Пожалуйста, отметьте этот ответ как решение, скрытие ошибки не является решением проблемы. Снимите перегрев лампы с вашего автомобиля, и вы увидите.
Давид Вартанян
133

Я бы не советовал Ричи ответить, потому что вы портите данные в базе данных. Вы не решите свою проблему, но попытаетесь «спрятать» ее и не сможете выполнить важные операции с базой данных с захваченными данными.

Если вы столкнулись с этой ошибкой, либо отправляемые вами данные не в кодировке UTF-8, либо ваше соединение не в кодировке UTF-8. Сначала убедитесь, что источником данных (файл, ...) действительно является UTF-8.

Затем проверьте подключение к вашей базе данных, вы должны сделать это после подключения:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

Затем убедитесь, что таблицы, в которых хранятся данные, имеют набор символов 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`
;

Наконец, проверьте настройки вашей базы данных:

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

Если источник, транспорт и пункт назначения - UTF-8, ваша проблема исчезла;)

Нико Гавенда
источник
1
@Kariem: Это странно, потому что этот параметр покрывается командой SET NAMES, что эквивалентно вызову SET character_set_client, SET character_set_results, SET character_set_connection dev.mysql.com/doc/refman/5.1/en/charset-connection.html
Нико Гавенда
2
Вторая команда должна быть SET CHARACTER SET utf8(не CHARACTER_SET)
кодер
6
Хотя этот ответ помогает исследовать проблему, он не отвечает, что делать, чтобы ее исправить. Я вижу «latin1» вместо «utf-8».
Вануан
2
этот ответ хорош при объяснении проблемы, но очень плох при детализации решения (именно об этом попросил OP). @nicogawenda: Какие все SQL-запросы нужно выполнить, чтобы полностью решить проблему? Как исправить все ранее существующие данные?
Клинт Иствуд
1
«Если источником, транспортом и пунктом назначения является UTF-8, ваша проблема исчезла;)» для меня это была хитрость
suarsenegger
80

Типы MySQL utf-8 на самом деле не являются правильными utf-8 - он использует до трех байтов на символ и поддерживает только базовый многоязычный план (т. Е. Не эмодзи, астральный план и т. Д.).

Если вам нужно хранить значения из более высоких плоскостей Unicode, вам нужны кодировки utf8mb4 .

moeffju
источник
9
Я думаю, что это, вероятно, лучшее решение. Обновите до 5.5 и замените utf8 на utf8mb4 в ответах выше. Я вставлял в Твиттер данные utf8, в которых были смайлики или другие символы, требующие 4 байта.
rmarscher
Допустим, мы не собираемся обновляться до 5.5. Как мы подавляем ошибки?
Пользователь
я слишком далеко прокрутил этот самый полезный ответ
handheldblender
1
10 лет с момента первоначального вопроса. Пусть будет известно, что кодировка utf8 в MySQL неверна. Используйте utf8mb4! То же самое касается MariaDB. Иначе у тебя не будет слез радости 😂
Лиам
51

Таблица и поля имеют неправильную кодировку; однако вы можете конвертировать их в 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
Я думаю, что это правильный ответ для всех. У меня есть две таблицы, каждая из которых имеет формат utf8 varchar. один из них получил ошибку, другой в порядке. даже если я пользователь 'update select' создаю копию из 'хорошего' столбца utf8 в другую таблицу, возникает та же ошибка. Это потому, что две таблицы созданы в разных версиях MySQL.
Айшигуан
Да! Это была неверная конфигурация из моей таблицы базы данных тоже. Я думаю, что этот ответ должен быть правильным. Моя проблема заключалась в том, что выбранный параметр сортировки был utf8_unicode_ci вместо utf8_general_ci. Спасибо :)
jprivillaso
2
Что этот ответ делает здесь, должен быть вверху
Сагун Шреста
1
этот помогает, он говорит вам, что попробовать, а не то, что может быть не так.
Виктор Ди
Спасибо! Это мне очень помогло. Я изменил таблицу сортировки и я подумал, что так и должно быть, но поля все еще были сопоставлены ...
Раду
25

Я решил эту проблему сегодня, изменив столбец на тип «LONGBLOB», который хранит необработанные байты вместо символов UTF-8.

Единственным недостатком этого является то, что вы должны позаботиться о кодировке самостоятельно. Если один клиент вашего приложения использует кодировку UTF-8, а другой - CP1252, возможно, ваши письма отправлены с неверными символами. Чтобы избежать этого, всегда используйте одну и ту же кодировку (например, UTF-8) во всех ваших приложениях .

Обратитесь к этой странице http://dev.mysql.com/doc/refman/5.0/en/blob.html для получения более подробной информации о различиях между TEXT / LONGTEXT и BLOB / LONGBLOB. Есть также много других аргументов в сети, обсуждающих эти два.

frankshaka
источник
1
Это решение кажется самым простым способом. Я попробовал несколько других кодировок без успеха.
Симеон Аболаринва
10

Сначала проверьте, является ли ваше default_character_set_name имя utf8.

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

Если результат не utf8, вы должны конвертировать вашу базу данных. Сначала вы должны сохранить дамп.

Чтобы изменить кодировку набора символов на UTF-8 для всех таблиц в указанной базе данных, введите в командной строке следующую команду. Замените DBNAME именем базы данных:

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

Чтобы изменить кодировку набора символов на UTF-8 для самой базы данных, введите следующую команду в приглашении mysql >. Замените DBNAME именем базы данных:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

Теперь вы можете повторить попытку ввода символа utf8 в вашу базу данных. Это решение помогает мне, когда я пытаюсь загрузить 200000 строк файла CSV в мою базу данных.

Бабакар Гингу
источник
8

Как правило, это происходит при вставке строк в столбцы с несовместимой кодировкой / сопоставлением.

Я получил эту ошибку, когда у меня были TRIGGER, которые по какой-то причине наследуют параметры сортировки сервера. И по умолчанию mysql (по крайней мере в Ubuntu) латиница-1 с шведским сопоставлением. Несмотря на то, что у меня была база данных и все таблицы, настроенные на UTF-8, мне еще предстояло установить my.cnf:

/etc/mysql/my.cnf:

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

И это должно перечислить все триггеры с utf8- *:

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

И некоторые из перечисленных переменных должны также иметь utf-8- * (без латинской-1 или другой кодировки):

show variables like 'char%';
Ондра Жижка
источник
6

Хотя ваша сортировка установлена ​​на utf8_general_ci, я подозреваю, что кодировка символов базы данных, таблицы или даже столбца может отличаться.

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
Самера Прасад Джаясингхе
источник
5

Я получил похожую ошибку ( Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1). Я попытался изменить набор символов столбца utf8mb4и после этого ошибка изменилась на 'Data too long for column 'content' at row 1'.
Оказалось, что MySQL показывает мне неправильную ошибку. Я вернул набор символов столбца в utf8и изменил тип столбца на MEDIUMTEXT. После этого ошибка исчезла.
Надеюсь, это кому-нибудь поможет.
Кстати MariaDB в том же случае (я тестировал тот же INSERT там) просто вырезал текст без ошибок.

AVKurov
источник
MySQL тоже Я устал от многих вещей, понял, что mysql не поддерживает 4-байтовое кодирование utf-8 в этой версии, и умирал, пытаясь понять, что вызывает это. Изменение типа, по-видимому, было ответом, немедленным решением.
Лиза
4

Эта ошибка означает, что либо у вас есть строка с неверной кодировкой (например, вы пытаетесь ввести кодированную строку ISO-8859-1 в столбец с кодировкой UTF-8), либо столбец не поддерживает данные, которые вы пытаетесь ввести.

На практике последняя проблема вызвана реализацией MySQL UTF-8, которая поддерживает только символы UNICODE, которым требуется 1-3 байта при представлении в UTF-8. Смотрите «Неверное строковое значение» при попытке вставить UTF-8 в MySQL через JDBC? для деталей.

Микко Ранталайнен
источник
2

Решение для меня, когда я столкнулся с этим неверным строковым значением: '\ xF8' для ошибки столбца с использованием сценария сценария, состоял в том, чтобы убедиться, что моя база данных настроена для utf8 общего ci, как и мои сопоставления полей. Затем, когда я делаю импорт данных из файла CSV, я загружаю CSV в UE Studio и сохраняю его в формате utf8 и Voila! Это работает как шарм, 29000 записей там без ошибок. Ранее я пытался импортировать CSV, созданный в Excel.

mainebrain
источник
2

Я перепробовал все вышеперечисленные решения (которые приносят действительные баллы), но у меня ничего не получалось.

Пока я не обнаружил, что в моих сопоставлениях таблиц MySQL в C # использовался неверный тип: MySqlDbType.Blob . Я изменил его на MySqlDbType.Text и теперь я могу написать все символы UTF8, которые я хочу!

PS Поле MySQL таблицы имеет тип "LongText". Однако когда я автоматически генерировал сопоставления полей с помощью программного обеспечения MyGeneration, он автоматически устанавливал тип поля как MySqlDbType.Blob в C #.

Интересно, что я использую тип MySqlDbType.Blob с символами UTF8 в течение многих месяцев без проблем, пока однажды я не попытался написать строку с некоторыми конкретными символами в ней.

Надеюсь, что это помогает кому-то, кто изо всех сил пытается найти причину ошибки.

Угний Раманаускас
источник
1

Я добавил двоичный файл перед именем столбца и решил ошибку кодировки.

вставить в tableA значения (двоичное stringcolname1);

Richardhe2007
источник
1

Привет, я также получил эту ошибку, когда я использую свои онлайн-базы данных с сервера Godaddy, я думаю, что он имеет версию MySQL 5.1 или более. но когда я делаю это с моего локального сервера (версия 5.7), все было в порядке, после этого я создал таблицу с локального сервера и скопировал ее на онлайн-сервер с помощью mysql yog. Я думаю, что проблема связана с набором символов

Скриншот здесь

Хашайн Лакшан
источник
1

Чтобы исправить эту ошибку, я обновил свою базу данных MySQL до utf8mb4, которая поддерживает полный набор символов Unicode, следуя этому подробному руководству . Я предлагаю внимательно изучить его, потому что есть немало ошибок (например, индексные ключи могут стать слишком большими из-за новых кодировок, после чего вам придется изменять типы полей).

metakermit
источник
1

Здесь есть хорошие ответы. Я просто добавляю свою, так как столкнулся с той же ошибкой, но это оказалось совершенно другой проблемой. (Возможно, на поверхности то же самое, но другая основная причина.)

Для меня ошибка произошла для следующего поля:

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

Это заканчивается сохранением в базе данных как двоичная сериализация URIкласса. Это не подняло никаких флагов при модульном тестировании (используя H2) или CI / интеграционном тестировании (используя MariaDB4j ), оно взорвалось в нашей производственной установке. (Хотя, как только проблема была понята, было достаточно легко увидеть неправильное значение в экземпляре MariaDB4j; это просто не взорвало тест.) Решением было создание специального преобразователя типов:

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

Используется следующим образом:

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

Что касается Hibernate, то, похоже, у него есть куча предоставляемых картографов типов , в том числе for java.net.URL, но не for java.net.URI(что нам здесь и нужно).

Сандер Верхаген
источник
1

В моем случае эта проблема была решена путем изменения кодировки столбца Mysql на «двоичный» (тип данных будет автоматически изменен на VARBINARY). Возможно, я не смогу фильтровать или искать по этому столбцу, но мне это не нужно.

WilyDen
источник
1

Если вам удалось обработать значение с помощью какой-либо строковой функции перед сохранением, убедитесь, что функция может правильно обрабатывать многобайтовые символы. Строковые функции, которые не могут этого сделать и, скажем, пытаются усечь, могут разбить один из одиночных многобайтовых символов в середине, что может привести к таким ситуациям со строковыми ошибками.

Например, в PHP вам нужно переключиться с substrна mb_substr.

WoodrowShigeru
источник
0

В моем случае сначала я встретил '???' на моем веб-сайте я проверяю набор символов Mysql, который теперь латинский, поэтому я изменяю его на utf-8, затем перезапускаю свой проект, затем я получаю ту же ошибку с вами, затем я обнаружил, что забыл изменить кодировку базы данных. и изменить в UTF-8, бум, это сработало.

acoder2013
источник
0

Я попробовал почти все шаги, упомянутые здесь. Никто не работал. Скачал мариадб. Это сработало. Я знаю, что это не решение, но это может помочь кому-то быстро определить проблему или дать временное решение.

Server version: 10.2.10-MariaDB - MariaDB Server
Protocol version: 10
Server charset: UTF-8 Unicode (utf8)
cherankrish
источник
0

В моем случае Incorrect string value: '\xCC\x88'...проблема заключалась в том, что о-умлаут был в разложенном состоянии. Этот вопрос-ответ помог мне понять разницу между и ö. В PHP исправление для меня состояло в том, чтобы использовать библиотеку PHP Normalizer . Например, Normalizer::normalize('o¨', Normalizer::FORM_C).

ММ.
источник
-2

1 - Вы должны заявить в вашей связи право присоединения UTF8. http://php.net/manual/en/mysqli.set-charset.php .

2 - Если вы используете строку mysql для выполнения скрипта, вы должны использовать флаг, например: 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

Роджер Гусмао
источник