2012-02-11 103 views
1

下面的代码是可运行和工作正常,但如果我改变$dbh->do("set names utf8");$dbh->do("set names gbk");,我会收到一个语法错误:为什么mysql似乎没有给我一个语法错误?

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/\' 与我试图存储到longblob的test.jpg图像文件相关联,因为如果使用文本编辑器打开图像文件,我可以找到相同的字符串。

奇怪的是,如果我更改$ dbh-> do(“set names utf8”),代码也可以工作。到$ dbh-> do(“set names gb2312”);为什么集名gbk语句给我一个语法错误?有什么显而易见的,我做错了吗?

感谢提前:)

我运行的activeperl 5.10.1和MySQL 5.5。

UPDATE

我已经找到了罪魁祸首!

此行local $/;正在导致MySQL语法错误。要解决这个问题,只需注释掉这一行。

我的Perl脚本是用GBK编码的,而且我的数据库表编码也是GBK,但是我还需要将设置名称添加到perl的DBI中,否则,插入到表格中的GBK字符将无法正确显示在GBK环境中。

UPDATE2

我想我已经解决了这一问题,但这个问题实际上依然存在。当我删除本地$ /;行,没有错误消息,但blob字段包含损坏的图像文件。

+0

什么类型是在要存储图像的数据表的第二列?由于使用不同的编码会得到不同的错误,因此它好像试图将图像二进制数据转换为字符串,而不是所有的字节组合都会生成有效的UTF-8。使用create table student(name varchar(20),pic longblob)创建 – 2012-02-11 12:15:00

+0

表;我显示的代码会生成完全错误消息。奇怪它包含两个“DBD :: mysql :: st执行失败”错误。它看起来像图像二进制数据正在处理为字符串。 – Mike 2012-02-12 09:25:40

+0

我自己不使用php,但它看起来好像查询试图将二进制转换为字符串。你有没有试过在bind_param中指定类型?像bind_param(2,$ image,SQL_LONGBLOB) – 2012-02-12 10:32:31

回答

3

GBK已过时,您不能再使用它了;和MySQL不支持目前的标准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 
); 

(我没有测试此代码。)

+0

感谢@daxim有关GB18030的信息。请参阅我更新的帖子。我发现导致MySQL语法错误的罪魁祸首。而且我无法仅处理Perl中的文本编码。如果不将GBK语句的设置名添加到DBI中,则插入到GBK编码表中的GBK编码字符将无法在GBK环境中正确显示。 – Mike 2012-02-12 01:53:45

相关问题