2011-10-28 9 views
5

Estoy tratando de escribir cadenas utf-8 en una tabla MySQL usando perl/DBI. Por algún motivo, la cadena se trunca en el primer carácter no ascii.cadena utf-8 que se trunca en la tabla MySQL usando Perl/DBI

Por ejemplo, si me juego hasta la siguiente tabla:

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

y ejecute el siguiente código 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')"); 

En realidad, escribe "N". (Cuando debería estar escribiendo "Nürburgring")

Mirando en el registro de consultas MySQL, veo esto:

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

lo que la cadena está alcanzando el servidor de base de datos intactos.

Si entro en la misma consulta directamente en la consola de MySQL:

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

La cadena entera está escrita correctamente. ¿Alguna idea de lo que estoy haciendo mal?

+0

¿Y qué escribe si cambia '\ xFC' a' ü' en su script? – TLP

+0

Hace exactamente lo mismo si uso un literal ü en el código perl. – plasticinsect

Respuesta

4

Estableció el atributo mysql_enable_utf8, por lo que le prometió a la interfaz que le dará una cadena Perl de caracteres. Sin embargo, este es un buffer de octetos en codificación Latin1.

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

La solución es simple. De cualquier anotar caracteres literales sin \x escapes, utilice el pragma utf8 para contar Perl que su código fuente está en UTF-8 y guardar la fuente de codificación UTF-8 con su editor ...

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"] 

... o decodificar los octetos en una cuerda. La mayoría de las veces no se trata de literales, sino de datos provenientes del exterior, así que mejor 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

Gracias por la explicación. Creo que lo entiendo ahora Cambié la línea de inserción a '$ dbh-> do (decodificar ('Latin1'," INSERT INTO testtable (textval) VALUES ('the N \ xFCrburgring') "));' y ahora funciona perfectamente. – plasticinsect

Cuestiones relacionadas