以下代码是可运行的,工作正常,但如果将$dbh->do("set names utf8");更改为$dbh->do("set names gbk");,将收到语法错误:

use strict;
use warnings;
use DBD::mysql;

my $dbh = DBI->connect("DBI:mysql:database=test;host=localhost","root","password");
$dbh->do("set names utf8");

open  my $jpg, '<', 'test.jpg' or die "$!";
binmode $jpg;
my $image = do{local $/; <$jpg>};
close $jpg;

 my $sql = "INSERT INTO student VALUES (?, ?)";

 my $sth = $dbh->prepare($sql);
 $sth->bind_param(1, 'Yang Liu');
 $sth->bind_param(2, $image);
 $sth->execute();
 $sth->finish;
 exit;

语法错误如下:
DBD::mysql::st execute failed: You have an error in your SQL syntax; check the m
anual that corresponds to your MySQL server version for the right syntax to use
near 'id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\' x
:xmptk' at line 1 at D:\sqltest.pl line 22.
DBD::mysql::st execute failed: You have an error in your SQL syntax; check the m
anual that corresponds to your MySQL server version for the right syntax to use
near 'id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\' x
:xmptk' at line 1 at D:\sqltest.pl line 22.

还有那条可疑的线
'id=\'W5M0MpCehiHzreSzNTczkc9d\'?>\n<x:xmpmeta xmlns:x=\'adobe:ns:meta/\'
与test.jpg图像文件关联,我正试图将其存储到longblob中,因为如果使用文本编辑器打开图像文件,我可以找到相同的字符串。
奇怪的是,如果我将$dbh->do(“set names utf8”);更改为$dbh->do(“set names gb2312”);为什么set names gbk语句会给出语法错误?有什么明显的我做错了吗?
提前谢谢:)
我运行的是ActivePerl 5.10.1和MySQL 5.5。
更新
我找到罪犯了!
此行local $/;导致MySQL语法错误。要解决这个问题,只需注释掉这一行。
我的Perl脚本是用GBK编码的,我的数据库表编码也是GBK,但是我还必须在Perl中将集合名称添加到DBI中,否则,插入到表中的GBK字符在GBK环境中不会正确显示。
更新2
我以为我已经解决了这个问题,但问题仍然存在。删除本地$/;行时,没有错误消息,但blob字段包含损坏的图像文件。

最佳答案

GBK已经过时,您不能再使用它了;MySQL不支持当前的标准GB 18030。
http://dev.mysql.com/doc/refman/5.5/en/faqs-cjk.html#qandaitem-B-11-1-1
http://www.gb18030.com/
http://zh.wikipedia.org/wiki/GB_18030
解决方法:不要set names,只使用Perl处理文本编码。将图像等二进制数据保留为八位字节。

use utf8;
use Encode qw(encode);
use Encode::HanExtra qw();
⋮
my $name = encode('GB18030', '刘阳', Encode::FB_CROAK | Encode::LEAVE_SRC);
$dbh->do(
    'INSERT INTO student VALUES (?, ?)',
    {},
    $name, $image
);

(我尚未测试此代码。)

07-28 00:16