繁体   English   中英

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

[英]How to connect to MySQL using UTF8 within a perl script?

简而言之:

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

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

详细:

我有与问题ERROR 1366 (HY000) 中描述的完全相同的问题:不正确的字符串值:'\xF0\x9F\x98\x9C' for column 'comment' at row 1 and even with the same Unicode character ( = 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 晚。
    ✅已检查

  • 将表的字符设置为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。
    这似乎是问题所在。 另一个问题的答案是

    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.

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

问题出在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}

我尝试了很多次,以多种不同的方式,使 cgi 脚本能够正常工作以从 STDIN 读取输入,读取 html 文件,将其打印到 STDOUT 并正确搜索 mysql 上的输入文本。 mysql 连接后的属性 mysql_enable_utf8mb4 和“SET NAMES utf8mb4”与“meta charset='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");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM