В чем причина того, что использование CONCAT() в чистой среде UTF-8 MySQL по-прежнему рассматривает конкатенированную строку (когда некоторый col в выражении является, например, int или date), как некоторая другая кодировка (возможно, Latin-1)?
среда MySQL, видимая с клиента (\s
):
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
Набор тестовых данных:
CREATE TABLE `utf8_test` (
`id` int(10) unsigned NOT NULL auto_increment,
`title` varchar(50) collate utf8_estonian_ci default NULL,
`year` smallint(4) unsigned NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_estonian_ci;
INSERT INTO utf8_test VALUES (1, 'Õäöüšž', 2011);
Этот запрос хорош:
SELECT id, title FROM utf8_test;
Это отключает флаг utf-8 (уже в MySQL, AFIU):
SELECT CONCAT(id, title) FROM utf8_test;
Из mysql-client все кажется прекрасным, потому что он настроен на отображение символов как UTF-8, но при запуске через Perl DBI все результаты запросов, содержащих CONCAT() внутри, не имеют установленного флага utf-8. Пример кода:
#!/usr/bin/perl
use strict;
use utf8::all;
use Encode qw(is_utf8);
my $dbh = your_db_connect_routine('test');
my $str = $dbh->selectrow_array('SELECT CONCAT(id, title) FROM utf8_test');
print "CONCAT: False\n" unless ( is_utf8($str) );
my $str = $dbh->selectrow_array('SELECT title FROM utf8_test');
print "NO CONCAT: False\n" unless ( is_utf8($str) );
Существует как минимум два обхода, которые я знаю
- запрос с помощью CAST()
SELECT CONCAT( CAST(id AS CHAR CHARACTER SET utf8), title) FROM utf8_test
- используя
$str = Encode::_utf8_on($str)
(считается плохой практикой?)
но я спрашиваю: почему это так в MySQL? Должен ли я считать его ошибкой или функцией?