Как подключиться к MySQL с помощью UTF8 в perl script?
В двух словах:
В Perl- Script: как мне подключиться к MySQL таким образом, который позволяет передавать четырехбайтовый символ Unicode U + 1F61C ( "😜" ) из perl script в MySQL-таблицу, где этот символ должен быть сохранен?
Использование {mysql_enable_utf8 => 1}
не решает проблему.
Подробнее:
У меня точно такая же проблема, как описано в вопросе ERROR 1366 (HY000): неправильное строковое значение: '\ xF0\x9F\x98\x9C' для столбца 'comment' at строка 1 и даже с одним и тем же символом Юникода (😜 = U + 1F61C = ЛИЦО С ВСТРОЕННЫМ ТОНКОЙ И ВЕКОВОЙ ГЛАЗА) который выдает сообщение об ошибке
DBD::mysql::st execute failed: Incorrect string value: '\xF0\x9F\x98\x9C' for column ...
Но я не использую PHP, я использую Perl.
В принятом ответе в другом вопросе говорится:
-
Запустить MySQL 5.5 или новее.
Я проверяю версию:
mysql> select version();
+-------------------------+
| version() |
+-------------------------+
| 5.7.13-0ubuntu0.16.04.2 |
+-------------------------+
Итак, это 5,7, которое позже 5.5.
✅checked
-
Установить символ таблицы utf8mb4
.
Я проверяю набор символов моей базы данных, моей таблицы и даже столбца с сообщением:
mysql> SELECT default_character_set_name FROM information_schema.SCHEMATA
-> WHERE schema_name = "myDatabase";
+----------------------------+
| default_character_set_name |
+----------------------------+
| utf8mb4 |
+----------------------------+
mysql> SELECT CCSA.character_set_name FROM information_schema.`TABLES` T,
-> information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
-> WHERE CCSA.collation_name = T.table_collation
-> AND T.table_schema = "myDatabase"
-> AND T.table_name = "myTable";
+--------------------+
| character_set_name |
+--------------------+
| utf8mb4 |
+--------------------+
mysql> SELECT character_set_name FROM information_schema.`COLUMNS`
-> WHERE table_schema = "myDatabase"
-> AND table_name = "myTable"
-> AND column_name = "myColumn";
+--------------------+
| character_set_name |
+--------------------+
| utf8mb4 |
+--------------------+
Таким образом, моя база данных, моя таблица и столбец с сообщением используют набор символов utf8mb4
.
✅checked
- Включить UTF8 в вашем подключении MySQL.
Кажется, это проблема. Ответ на другой вопрос гласит:
SET NAMES utf8
или используйте параметр при подключении, который аналогичным образом включает его.
Я не знаю, как SET NAMES utf8
в perl script, поэтому я сделал это, как я это делал за последние годы. Я думаю, что это "вариант при подключении, который так же позволяет это".
Это в конце длинной строки, начинающейся с my $dbh = DBI->connect
:
#!/usr/bin/perl -w
use strict;
use warnings;
use utf8;
use Encode;
use DBI;
binmode STDOUT, ":utf8";
#Here I connect using the parameter mysql_enable_utf8 (create database handle):
my $dbh = DBI->connect('DBI:mysql:database=myDatabase;host=localhost','aUser','aPassword',{mysql_enable_utf8 => 1});
#Prepare the statement (create statement handle):
my $sth = $dbh->prepare('INSERT INTO `myTable` (`myColumn`) VALUES(?);');
#This doesn't work:
$sth->execute('😜');
#This doesn't work either:
$sth->execute(encode_utf8('😜'));
#end processing:
$dbh->disconnect();
exit(0);
Оба запускают одну и ту же ошибку (изменяется только номер строки в конце):
DBD::mysql::st execute failed: Incorrect string value: '\xF0\x9F\x98\x9C' for column 'myColumn' at row 1 at myTestScript.pl line 16.
Что я делаю неправильно?
Как я могу сделать это лучше?
Ответы
Ответ 1
Проблема заключается в команде SET NAMES utf8
. В MySQL набор символов utf8 не является действительно utf8, он поддерживает символы только с 3 байтами, и этот символ имеет 4 байта:
Набор символов utf8 в MySQL имеет следующие характеристики:
• Нет поддержки дополнительных символов (только символы BMP).
• Максимум три байта на многобайтовый символ.
Истинным utf8 является utf8mb4, который вы используете как набор символов в самом поле. Итак, используйте SET NAMES utf8mb4
Итак, из Perl вы должны использовать {mysql_enable_utf8mb4 => 1}
вместо {mysql_enable_utf8 => 1}
.