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

j8yoct9x  于 2023-01-20  发布在  Mysql
关注(0)|答案(2)|浏览(173)

简而言之:

在Perl脚本中:如何以允许将四字节unicode字符U +1F61C("")从Perl脚本传输到应该存储该字符的MySQL-Table的方式连接到MySQL?😜") from the perl script to a MySQL-Table where this character should be stored?
使用{mysql_enable_utf8 => 1}不能解决问题。

详情:

我遇到的问题与问题ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x98\x9C' for column 'comment' at row 1中描述的问题完全相同,即使使用相同的Unicode字符(= U +1F61C = FACE WITH STUCK-OUT TONGUE AND WINKING EYE)也会产生错误消息😜 = U+1F61C = FACE WITH STUCK-OUT TONGUE AND WINKING EYE ) which produces the error message

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。
已检查

      • 将表格字符设置为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
已检查

      • 在MySQL连接上启用UTF8。**

这似乎是问题所在。answer to the other question说:
SET NAMES utf8,或者在连接时使用类似的选项来启用它。
我不知道如何在perl脚本中使用SET NAMES utf8,所以我在过去几年中一直是这样做的,我认为这是"* 连接时的一个选项,类似地启用它 *"。
它位于以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.

我哪里做错了?
我怎样才能做得更好?

xkftehaa

xkftehaa1#

问题出在SET NAMES utf8命令上。在MySQL中,utf8字符集不是真正的utf8,它是supports characters up 3 bytes only,并且所讨论的字符有4个字节:
MySQL中的utf8字符集具有以下特征:
·不支持补充字符(仅限BMP字符)。
·每个多字节字符最多三个字节。
真正的utf8是在字段本身中用作字符集的utf8mb4。
因此,在Perl中,您应该使用{mysql_enable_utf8mb4 => 1}而不是{mysql_enable_utf8 => 1}

2izufjch

2izufjch2#

我尝试了很多次,用了很多不同的方法,cgi脚本可以正确地从STDIN读取输入,读取html文件,打印到STDOUT并正确地在mysql上搜索输入的文本。mysql_enable_utf8mb4属性和mysql连接后的“设置名称utf8 mb 4”可以正确地与“ metacharset ='UTF-8'”一起工作。

#!/usr/bin/perl
print "Content-type: text/html; charset=UTF-8\n\n";

#use utf8;
#use open ':utf8';
#binmode STDOUT, ":utf8";
#binmode STDIN , ":utf8";
#use encoding 'utf8';

our $dbh = DBI->connect("DBI:mysql:database=$database;host=$servername;port=$port",$username,$password, {PrintWarn => 0, PrintError => 0, mysql_enable_utf8mb4 => 1}) || die;
$dbh->do("SET NAMES utf8mb4");

相关问题