Подтвердить что ты не робот

Почему CONCAT() не использует по умолчанию кодировку по умолчанию в MySQL?

В чем причина того, что использование 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? Должен ли я считать его ошибкой или функцией?

4b9b3361

Ответ 1

Это хорошо известная ошибка в MySQL. Он исправлен в MySQL 5.5

Смотрите: http://bugs.mysql.com/bug.php?id=12030

Проблема связана с объединением целого числа с varchar.

Работа вокруг заключается в том, чтобы сначала передать id (целое число) в char, а затем объединить, то есть:

SELECT CONCAT(cast(id as char), title) FROM utf8_test

Ответ 2

Вероятно, это проблема DBD:: mysql/особенность. Попробуйте включить utf8 в дескрипторе базы данных, как описано в POD для DBD::mysql (mysql_enable_utf8 part).

Эта старая (Perl 5.8 раз) статья также может помочь.