如何在perl脚本中使用UTF8连接MySQL?

Hub*_*ast 17 mysql unicode perl utf-8

简而言之:

在Perl-Script中:如何以允许将perl脚本中的四字节unicode字符U + 1F61C("")传输到应存储此字符的MySQL-Table的方式连接到MySQL?

使用{mysql_enable_utf8 => 1}并不能解决问题.

详细地:

我有与问题错误1366(HY000)中描述的完全相同的问题:错误的字符串值:'\ xF0\x9F\x98\x9C'用于第1行的"注释"列,甚至具有相同的Unicode字符(= U + 1F61C = 带有踩踏舌片和眨眼的脸部,产生错误信息

DBD::mysql::st execute failed: Incorrect string value: '\xF0\x9F\x98\x9C' for column ...
Run Code Online (Sandbox Code Playgroud)

但我不使用PHP,我使用Perl.

另一个问题中接受的答案是:

  • 运行MySQL 5.5或更高版本.
    我查看版本:

    mysql> select version();
    +-------------------------+
    | version()               |
    +-------------------------+
    | 5.7.13-0ubuntu0.16.04.2 |
    +-------------------------+
    
    Run Code Online (Sandbox Code Playgroud)

    所以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            |
    +--------------------+
    
    Run Code Online (Sandbox Code Playgroud)

    所以我的数据库,我的表和报告的列都使用字符集utf8mb4.
    ✅checked

  • 在MySQL连接上启用UTF8.
    这似乎是个问题.另一个问题答案是:

    SET NAMES utf8,或在连接时使用选项,类似地启用它.

我不知道如何SET NAMES utf8在perl脚本中,所以我做了它是如何在过去几年中做到的.我认为这是" 连接时的一个选项,类似地启用它 ".
它位于长线的末尾,开头是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);
Run Code Online (Sandbox Code Playgroud)

两者都执行相同的错误(只有最后的行号改变):

DBD::mysql::st execute failed: Incorrect string value: '\xF0\x9F\x98\x9C' for column 'myColumn' at row 1 at myTestScript.pl line 16.
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?
我怎样才能做得更好?

Sha*_*dow 16

问题出在SET NAMES utf8命令上.在MySQL中,utf8字符集不是真正的utf8,它仅支持3个字节的字符,并且所讨论的字符有4个字节:

MySQL中的utf8字符集具有以下特征:

•不支持增补字符(仅限BMP字符).

•每个多字节字符最多三个字节.

真正的utf8是你在字段中用作字符集的utf8mb4.所以,使用SET NAMES utf8mb4

所以从Perl你应该使用{mysql_enable_utf8mb4 => 1}而不是{mysql_enable_utf8 => 1}.