Неверное строковое значение: проблема MySQL при вставке текста UTF8 в столбец latin1

У меня есть таблица MySQL в производстве с кодировкой latin1_swedish_ci (она же latin1).

Прямо сейчас есть это входящее содержимое ( String : "한밤의" ) в формате UTF-8, которое необходимо вставить в это поле столбца TEXT, называемое keywords в таблице.

Когда я пытаюсь выполнить INSERT, я получаю эту ошибку:

Incorrect string value: '\xED\x95\x9C\xEB\xB0\xA4...' for column 'keywords' at row 1

Я пробовал всевозможные способы в своем коде Java, чтобы попытаться преобразовать UTF8 в ISO-8859-1, как показано ниже, и я все еще получаю ту же ошибку:

String convertedString = new String(originalString.getBytes("UTF-8"), "ISO-8859-1");

Я знаю, что в StackOverflow есть решения, в которых упоминается изменение кодировки таблицы MySQL на UTF8 с latin1, и я, к сожалению, не могу этого сделать, потому что это главный сервер MySQL в реальном времени, а также исторически он использовал latin1.

Есть ли у кого-нибудь предложения по исправлению этой ошибки «Неверное строковое значение»?

Спасибо.


person user1805458    schedule 06.05.2016    source источник
comment
Вам нужно изменить кодировку в Java с usc2 на utf8. ISO-8859-1 никоим образом не участвует в том, что вы показываете. Вы надеялись на 한밤, верно?   -  person Rick James    schedule 06.05.2016
comment
Привет, Рик Джеймс, спасибо за быстрый ответ. Что вы имеете в виду под изменением кодировки с usc2 на utf8? Извините, я не слежу. И да, я хотел бы попасть в 한밤   -  person user1805458    schedule 06.05.2016
comment
Таким образом, раньше был старый скрипт Python, который считывал этот текст Unicode из другой базы данных MySQL (в utf-8) и записывал его в эту базу данных latin1 MySQL, и этот текст отображался как '•œë°¤ì˜ Если я могу понять, как преобразовать 한밤의 в í•œë°¤ì˜ в моем коде Java, тогда я в порядке   -  person user1805458    schedule 06.05.2016


Ответы (2)


То, что вы пытаетесь сделать, просто невозможно, если только символы в строке utf8 также не имеют представлений в latin1... а latin1 - это крошечный однобайтовый набор символов (всего менее 256 возможных символов), поэтому подавляющее большинство допустимых символов utf8 не имеют эквивалентного представления latin1.

Вы не можете хранить в столбце символы, которые не поддерживаются набором символов столбца. Дело не в "превращении" одного в другое.

Если вам нужен юникод, вам нужен как минимум столбец utf8, и изменение таблицы — единственная альтернатива. Попытка сделать иначе подобна попытке сохранить отрицательное число в столбце целого числа без знака. Беззнаковые целые числа не могут быть отрицательными — это не вопрос преобразования.

Это верно для любой СУБД, поддерживающей символьные типы данных, и не является ограничением, специфичным для MySQL.

person Michael - sqlbot    schedule 06.05.2016
comment
Привет Михаил, спасибо за ответ. Таким образом, раньше был старый скрипт Python, который считывал этот текст Unicode из другой базы данных MySQL (в utf-8) и записывал его в эту базу данных latin1 MySQL, и этот текст отображался как '•œë°¤ì˜ Если я могу понять, как преобразовать 한밤의 в í•œë°¤ì˜ в моем коде Java, тогда я в порядке - person user1805458; 06.05.2016

한밤 — это моджибаке для 한밤 — вот где на каком-то этапе он был преобразован в latin1. Но \ud55c\ubc24 - это Юникод. В каком режиме находится Python? У вас это в начале?

# -*- coding: utf-8 -*- 

дополнительный контрольный список Python.

Еще

предпочтительнее utf8; экр возможно. Но... Проблема не в выборе набора символов, а в согласованности во всем приложении при указании этого набора символов.

Вы используете Python? Это помечено Java?

Для Java/JDBC вам нужно ?useUnicode=yes&characterEncoding=UTF-8 в вызове getConnection().

Вам нужно это:

  • Байты в вашем клиенте должны быть utf8, например шестнадцатеричный ED959C. (Все корейские символы в utf8 занимают 3 байта.)
  • Соединение между клиентом и сервером должно быть utf8. Выполнение SET NAMES utf8 сразу после подключения — еще один способ сделать это.
  • Столбец/таблица должна быть CHARACTER SET utf8.
  • Если вы используете html, вам понадобится <meta charset=UTF-8>.

Для корейского utf8mb4 так же хорошо, как utf8. Проверьте эти 4 пункта выше и «докажите» нам, что вы делаете их все.

Для сервлетов JSP и Java немного отличается рекомендация. гарантировано.

person Rick James    schedule 07.05.2016
comment
Привет, Рик, да, я вижу # -- coding: utf-8 -- вверху файла Python - person user1805458; 07.05.2016
comment
Что-нибудь полезное в ссылке контрольного списка? - person Rick James; 07.05.2016
comment
К сожалению, пока нет, но я пытался использовать другое преобразование в коде Java. Когда я пытаюсь преобразовать в Cp1252 вместо ISO-8859-1, используя new String(keywords.getBytes(UTF-8), Cp1252), я заметил кое-что интересное. - person user1805458; 08.05.2016
comment
В Java, когда я преобразовываю корейские символы Unicode в Cp1252, я получаю '•œë°¤ì�, что вызывает неверное строковое значение: '\xEF\xBF\xBD\xCB\x9CT...' для столбца "ключевые слова" в ошибка 1 ряда. Однако, когда он был записан Python в MySQL, он был '•œë°¤ì , и это прекрасно записывается в столбец MySQL latin1! Единственная разница в том, что последний символ, и я все еще пытаюсь понять, как я могу получить тот же результат для Java, что и в Python - person user1805458; 08.05.2016
comment
CP1252 имеет 256 различных символов. У корейцев около 11000. Проще говоря, корейский язык не может быть представлен в CP1252, поэтому не используйте CP1252 для корейского текста. - person Rick James; 09.05.2016
comment
MySQL latin1 ничего не проверяет; он возьмет байты, которые вы ему дадите, и сохранит их. Одиночный символ представлен как 3 байта в utf8 (hex ED959C). Если эти 3 байта хранятся в столбце latin1, они обрабатываются как эти 3 символа latin1 í•œ. Также избегайте latin1. - person Rick James; 09.05.2016
comment
Я понимаю. Итак, если CP1252 и ISO-8859-1 (latin1) отсутствуют, есть ли другие варианты преобразования Java в new String(originalString.getBytes(UTF-8), Some charset); чтобы по-прежнему иметь возможность конвертировать 한 в í•œ? Это все возможные варианты правильной кодировки: docs.oracle.com/javase/8/docs/technotes/guides/intl/ - person user1805458; 09.05.2016
comment
Я использую Java 8 с использованием фреймворка REST Джерси. Код Python — это то, что я пытаюсь заменить, потому что он очень старый и неэффективный. Я использую useUnicode=yes&characterEncoding=UTF-8, когда подключаюсь к своей базе данных MySQL, и все равно выдает ошибку Incorrect String Value. Клиент, который отправляет HTTP POST на сервер Java, выполняет POST в utf-8. Что касается самого столбца MySQL, который находится в latin1, мы, к сожалению, не можем изменить его на utf-8. - person user1805458; 10.05.2016
comment
Вы должны найти способ изменить столбец на utf8. Если Джерси не позволит тебе это сделать, избавься от Джерси. - person Rick James; 10.05.2016