У меня есть DB с utf8 по умолчанию charset и таблица, которая содержит строки с символами non-ascii. Я правильно читаю данные с помощью клиентской программы mysql
и клиентской программы isql
odbc (см. Примеры ниже). Однако, когда я читаю таблицу в своем клиенте на С++, используя libodbС++ оболочку odbc, я получаю мусор.
Любопытно, что я использовал настройки MySql по умолчанию до сих пор, т.е. latin1
charset, но на самом деле данные содержали строки utf8. Таким образом, я получал utf8 в порядке. Я изменил DB на utf8, чтобы использовать сортировку utf8_bin
.
Так как я использую set names utf8
в клиенте, я не ожидаю, что между клиентом и сервером не произойдет преобразования кодировки. Я ошибаюсь?
Знаете ли вы о проблемах с кодировкой с libodbС++?
EDIT: просто протестировал это с помощью "чистого" клиента odbc (отвратительно...), работает нормально. Странно, поскольку libodbС++ - это просто оболочка для odbc, я ожидаю, что это не повлияет на данные. В любом случае, подозреваемый является библиотекой libodbС++.
mysql> show full columns from tbl_list_domains;
+-------+-----------+-----------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+-----------+-----------+------+-----+---------+-------+---------------------------------+---------+
| word | char(100) | utf8_bin | NO | PRI | NULL | | select,insert,update,references | |
+-------+-----------+-----------+------+-----+---------+-------+---------------------------------+---------+
$ mysql -u mysql navajoLocal <<< "set names utf8; select * from tbl_list_domains order by word limit 30" > out
Файл out
выглядит хорошо:
word
aa
ab
ac
ad
ae
...etc.
Использование isql
клиента odbc:
echo -e "set names utf8 \n select * from tbl_list_domains order by word limit 30" |isql mysql3-test -v -b -x0x20 > out
все еще хорошо.
однако это:
int main()
{
ConnectionPtr conn = ConnectionPtr( DriverManager::getConnection("Driver=mysql3;database=navajoLocal;server=localhost;user=mysql;option=3;socket=/var/lib/mysql/mysql.sock") );
StatementPtr st = StatementPtr( conn->createStatement() );
st->executeUpdate("set names utf8 collate utf8_bin");
ResultSetPtr res = ResultSetPtr( st->executeQuery("select word from tbl_list_domains order by word limit 30") );
string s;
while (res->next()) {
s = res->getString(1);
cout << s << endl;
}
}
выдает следующее:
a^@
a^@
a^@
a^@
Хорошо, нашел виновным - это библиотека libodbc++
, как говорит редактирование. Иду писать авторам. Решение заключалось бы в замене его на соединитель MySql С++. Они оба моделируются после JDBC, поэтому изменения невелики. Надеюсь, я скоро не изменю БД...
Я не знаю, ваша проблема такая же, как у меня. Я пытался получить результат поиска из базы данных utf8_bin, используя PHP и MySQL DB, но utf8_bin очень строг, когда говорит о похожих символах (например, e é ë). Таким образом, когда запрос используется без правильных символов utf8 и/или случая, он не возвращает результаты или, по крайней мере, ожидаемые. Итак, мой оракул Google показал в MySQL, что разрешает мне использовать _utf8 (обратите внимание на подчеркивание) и collate utf8_unicode_ci в предложении SELECTS WHERE, например:
SELECT field1,field2,field3
FROM `table1`
WHERE `table`.`field2` LIKE _utf8 '%$q%' collate utf8_unicode_ci
Надеюсь, он решает вашу проблему. P.S.: Извините за мой английский. Это не мой первый язык.
_utf8
является представителем (как здесь dev.mysql.com/doc/refman/5.1/en/charset-literal.html ). Недостатком такого подхода является то, что преобразование выполняется во время выполнения запроса и занимает много времени. И не беспокойтесь о своем английском - это не родной язык для большинства из нас :)