Besides the encoding problem, I don’t think there is a guarantee that valuesit will always give the fields in the same order. You can get different hashref values from fetchrow_hashrefevery time you call it. The solution to this is to use fetchrow_arrayref.
Text :: CSV recommends Text :: CSV :: Encoded
my $csv = Text::CSV::Encoded->new({ eol => "\015\012" });
open my $fh, '>:raw', 'Foo.csv';
my $sth = $dbh->prepare("SELECT * FROM Foo");
$sth->execute();
$csv->print($fh, $sth->{NAME_lc});
while (my $row = $sth->fetchrow_arrayref) {
$csv->print($fh, $row);
}
, :
use Encode 'find_encoding';
my $utf8 = find_encoding('utf8');
my $csv = Text::CSV->new({ binary => 1, eol => "\015\012" });
open my $fh, '>:raw', 'Foo.csv';
my $sth = $dbh->prepare("SELECT * FROM Foo");
$sth->execute();
$csv->print($fh, $sth->{NAME_lc});
while (my $row = $sth->fetchrow_arrayref) {
$csv->print($fh, [ map { $utf8->encode($_) } @$row ]);
}