2011-10-28 60 views
5

我想使用perl/DBI將utf-8字符串寫入MySQL表。出於某種原因,字符串在第一個非ASCII字符處被截斷。使用Perl/DBI在MySQL表中截斷utf-8字符串

例如,如果我下表設置:

CREATE DATABASE testdb DEFAULT CHARSET=utf8; 
CREATE TABLE testdb.testtable (textval CHAR(30)) DEFAULT CHARSET=utf8; 

然後運行下面的Perl代碼:

#!/usr/bin/perl 
use strict; 
use DBI; 
my $dbh = DBI->connect('DBI:mysql:host=localhost;database=testdb', 'testuser', 'somepassword', {mysql_enable_utf8 => 1}) or die $DBI::errstr; 
$dbh->do('SET NAMES utf8'); 
$dbh->do("INSERT INTO testtable (textval) VALUES ('the N\xFCrburgring')"); 

它實際上寫的 「N」。 (當它應該寫「紐伯格林」)

尋找在MySQL查詢日誌,我看到:

271 Query INSERT INTO testtable (textval) VALUES ('the Nürburgring') 

所以串到達DB服務器完好。

如果我直接在MySQL控制檯中輸入相同的查詢:

INSERT INTO testtable (textval) VALUES ('the Nürburgring'); 

整個字符串被正確寫入。任何想法我做錯了什麼?

+0

又是什麼,如果你改變'\ xFC'爲'在你的腳本ü'寫? – TLP

+0

如果我在perl代碼中使用文字ü,它完全一樣。 – plasticinsect

回答

4

您設置了屬性mysql_enable_utf8,因此您承諾將爲其提供一個Perl字符串的接口。但是,這是Latin1編碼中的八位組的緩衝區。

use Devel::Peek qw(Dump); 
Dump "the N\xfcrburgring"; 
# FLAGS = (POK,READONLY,pPOK) 
# PV = 0x208e4f0 "the N\374rburgring"\0 

修復很簡單。無論譜寫的文字字符不\x逃逸,使用utf8編譯來告訴Perl你的源代碼是UTF-8並保存UTF-8編碼的源與您的編輯器...

use utf8; 
use Devel::Peek qw(Dump); 
Dump "the Nürburgring"; 
# FLAGS = (POK,READONLY,pPOK,UTF8) 
# PV = 0x20999f0 "the N\303\274rburgring"\0 [UTF8 "the N\x{fc}rburgring"] 

...或八位字節解碼成一個字符串。大多數情況下,你處理的不是文字,而是數據來自外部,所以更好learn about the whole topic of encoding

use Encode qw(decode); 
use Devel::Peek qw(Dump); 
Dump decode 'Latin1', "the N\xfcrburgring"; 
# FLAGS = (TEMP,POK,pPOK,UTF8) 
# PV = 0x208f6b0 "the N\303\274rburgring"\0 [UTF8 "the N\x{fc}rburgring"] 
+0

謝謝你的解釋。我想我現在明白了。我將插入行更改爲'$ dbh-> do(decode('Latin1',「INSERT INTO testtable(textval)VALUES('N \ xfrburgring')」));'現在它完美地工作。 – plasticinsect