Як виправити помилки "Неправильне значення рядка"?


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 буде досить дозвільним)
  • Як я можу це виправити?
  • Які ймовірні наслідки такої виправлення?

Я вважав, що переходити на varf utf8 ([деяка велика кількість]) із увімкненим бінарним прапором, але я досить незнайомий з 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 Western European") є найбільш дозволеним кодуванням там - кожне байтове значення є дійсним кодовим пунктом.

Звичайно, справжній UTF-8 вже не зрозуміє, ані будь-яке інше не-cp1252 кодування, але це здається, що ви не надто переймаєтесь цим?


4
Що саме ви маєте на увазі під "Звичайно, справжній UTF-8 вже не зрозуміє?"
Брайан

5
@Brian: Якщо ви скажете йому, що ви даєте йому cp1252, а ви фактично даєте йому UTF-8 за, скажімо café, це буде неправильно трактувати це як café. Він не вийде з ладу, але неправильно зрозуміє високорозрядних символів.
RichieHindle

3
@Richie: База даних може із задоволенням називати дані все, що вона хоче, але якщо php-код, який захоплює, заповнює їх у рядок, це не матиме великої різниці ... чи не так? Я не бачу, де саме нерозуміння UTF-8 впливає.
Брайан

7
@Brian: Ні, ти маєш рацію. Час, який би змінився, був би в базі даних, наприклад, якщо ви використовували пункт 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 znak_set_resulta
nico gawenda

2
Другою командою має бути SET CHARACTER SET utf8(не CHARACTER_SET)
Coder

6
Хоча ці відповіді допомагають дослідити проблему, вона не відповідає, що робити для її усунення. Я бачу "latin1" замість "utf-8".
Вануан

2
ця відповідь чудово пояснює проблему, але дуже погана в деталізації рішення (саме про це вимагала ОП). @nicogawenda: Які всі запити SQL слід запустити, щоб повністю виправити проблему? Як виправити всі наявні дані?
Клінт Іствуд

1
"Якщо джерелом, транспортом та пунктом призначення є UTF-8, вашої проблеми немає;)" це було для мене
хитрістю

80

Типи utf-8 MySQL насправді не є належними utf-8 - він використовує лише три байти на персонаж і підтримує лише основну багатомовну площину (тобто немає Емодзі, немає астральної площини тощо).

Якщо вам потрібно зберігати значення з вищих площин Unicode, вам потрібні кодування utf8mb4 .


9
Я думаю, що це, мабуть, найкраще виправлення. Оновіть до 5.5 та замініть utf8 на utf8mb4 у наведених вище відповідях. Я вставляв utf8 дані з Twitter, в яких були емоджи або інші символи, для яких потрібно 4 байти.
rmarscher

Припустимо, ми не збираємось переходити на 5,5. Як ми придушуємо помилки?
Користувач

Я занадто далеко прокрутив цю найкориснішу відповідь
handheldblender

1
10 років з моменту первинного питання. Нехай буде відомо, що кодування utf8 MySQL не є належним utf8. Використовуйте 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. один з них отримав помилку, інший - добре. навіть я користувачем 'update select' роблю копію зі стовпця 'good' utf8 в іншу таблицю, трапляється така ж помилка. Це тому, що дві таблиці створені в різних версіях MySQL.
АйШігуанг

Так! Це була неправильна конфігурація і з моєї таблиці баз даних. Я думаю, що ця відповідь повинна бути правильною. Моя проблема полягала в тому, що вибране співставлення було utf8_unicode_ci замість utf8_general_ci. Дякую :)
jprivillaso

2
Що ця відповідь робить тут, має бути вгорі
Сагун Шрестха

1
цей допомагає, він говорить вам, що спробувати, замість того, що може бути неправильним.
Віктор Ді

Дякую! Просто мені це дуже допомогло. Я змінив таблицю зіставлення мурашок, я подумав, що так, але поля все ще порівнювали ascii ...
Раду

25

Я вирішив цю проблему сьогодні, змінивши стовпчик на тип "LONGBLOB", який зберігає необроблені байти замість символів UTF-8.

Єдиним недоліком цього є те, що вам потрібно подбати про кодування самостійно. Якщо один клієнт вашої програми використовує кодування UTF-8, а інший використовує CP1252, ви можете надсилати електронні листи з неправильними символами. Щоб цього уникнути, завжди використовуйте однакове кодування (наприклад, UTF-8) у всіх своїх програмах .

Докладніші відмінності між TEXT / LONGTEXT та BLOB / LONGBLOB див. На цій сторінці http://dev.mysql.com/doc/refman/5.0/en/blob.html . В Інтернеті також є багато інших аргументів, які обговорюють ці два.


1
Це рішення здається найпростішим шляхом. Я спробував кілька інших кодувань без успіху.
Симеон Аболарінва

10

Спершу перевірте, чи вказано ваше ім'я_замовника_характер_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 у тому самому випадку (я тестував ту саму ВНУТКУ) просто вирізав текст без помилок.


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 записів в ньому немає помилок. Раніше я намагався імпортувати Excel, створений csv.


2

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

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

ps Поле таблиці MySQL типу "LongText". Однак, коли я автоматично генерував відображення поля за допомогою програмного забезпечення MyGeneration, він автоматично встановлював тип поля як MySqlDbType.Blob у C #.

Цікаво, що я багато місяців без проблем використовував тип MySqlDbType.Blob з символами UTF8, поки одного разу я не спробував написати рядок з деякими певними символами в ньому.

Сподіваюсь, це допомагає тому, хто намагається знайти причину помилки.


1

Я додав двійковий файл перед назвою стовпця і вирішувати помилку діаграми.

вставити в таблицюAA значення (двійкове рядкове ім'я1);


1

Привіт, я також отримав цю помилку, коли я використовую мої онлайн-бази даних з godaddy-сервера, я думаю, що вона має версію mysql 5.1 або більше. але коли я з мого локального сервера (версія 5.7) було добре, після цього я створив таблицю з локального сервера і скопіював на інтернет-сервер за допомогою mysql yog, я думаю, що проблема полягає в наборі символів

Знімок екрана


1

Щоб виправити цю помилку, я оновив свою базу даних MySQL до utf8mb4, яка підтримує повний набір символів Unicode, дотримуючись цього детального посібника . Я пропоную ретельно пройти через це, оскільки є досить багато ґутчей (наприклад, індексні ключі можуть стати занадто великими через нові кодування, після яких вам доведеться змінювати типи полів).


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, то, здається, у нього є маса наданих картографічних типів , в тому числі для java.net.URL, але не для java.net.URI(що тут нам потрібно).


1

У моєму випадку ця проблема була вирішена шляхом зміни кодування стовпця Mysql на 'двійковий' (тип даних буде автоматично змінено на VARBINARY). Можливо, я не зможу фільтрувати або шукати за допомогою цього стовпця, але мені це не потрібно.


1

Якщо вам трапляється обробляти значення за допомогою якоїсь строкової функції перед збереженням, переконайтеся, що функція може правильно обробляти багатобайтові символи. Функції рядків, які не можуть цього зробити, і це, скажімо, спроба урізати, можуть розділити один із окремих багатобайтових символів посередині, і це може спричинити такі строкові помилки.

У PHP, наприклад, вам потрібно буде перейти від substrдо mb_substr.


0

У моєму випадку я спершу зустрічаю "???" на моєму веб-сайті, тоді я перевіряю набір символів Mysql, який є латинською мовою, тому я зміню його на utf-8, потім я перезапускаю проект, тоді я отримав таку ж помилку з вами, тоді я виявив, що я забуваю змінити схему бази даних і перейти на utf-8, бум, він спрацював.


0

Я намагався майже всі зазначені тут кроки. Жоден не працював. Завантажили маріадб. Це спрацювало. Я знаю, що це не рішення, але це може допомогти комусь швидко визначити проблему або дати тимчасове рішення.

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

0

У моєму випадку Incorrect string value: '\xCC\x88'...проблема полягала в тому, що o-umlaut знаходився в своєму розкладеному стані. Це запитання і відповіді допомогло мені зрозуміти різницю між та ö. У PHP для мене виправкою було використання бібліотеки нормалізаторів PHP . Наприклад, 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.