【问题标题】:Why CONCAT() does not default to default charset in MySQL?为什么 CONCAT() 在 MySQL 中不默认为默认字符集?
【发布时间】:2011-09-17 20:05:03
【问题描述】:

在纯 UTF-8 环境中使用 CONCAT() 的原因是什么,MySQL 仍然将连接字符串(当表达式中的某些 col 是 int 或 date 时)视为其他字符集(可能是 Latin-1)?

从客户端 (\s) 看到的 MySQL 环境:

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 中?我应该将其视为错误还是功能?

【问题讨论】:

  • 除了 Perl DBI 之外的其他客户端会发生什么?例如,MySQL GUI 工具或其他语言?您还尝试过替代驱动程序,例如DBD::Wire10
  • @Dan: DBD::Wire10 有同样的行为。但在 Python 中可以正常工作。 DBI 中还有问题吗?

标签: mysql perl utf-8


【解决方案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

【讨论】:

  • 不仅整数,而且时间戳也会导致问题。感谢您的解决方法! +1
  • 时间戳反正已经存储为 INT,所以如果你处理所有 INT 列,应该没问题。
【解决方案2】:

这可能是 DBD::mysql 问题/特殊性。尝试按照POD for DBD::mysqlmysql_enable_utf8 部分)中所述在数据库句柄中启用 utf8。

这个老(Perl 5.8 倍)article 也能帮上忙。

【讨论】:

  • 正如我对 Dan 的回答:与 DBD::Wire10 驱动程序的行为相同。对于DBD::mysql mysql_enable_utf8 也在连接功能中。而且我不明白,查询如何影响 DBI 或 DBD::* 级别?
  • 在 CentOS 7 上使用供应商提供的 perl-DBD-MySQL-4.023-6,我仍然必须使用 $dbh->do('SET NAMES utf8');(如您链接到的文章中所述),即使我的服务器、架构、表和列是所有 utf8,带有 utf8 排序规则。所以看来 Perl DBD::mysql 客户端似乎默认为“latin1”是我的问题。
猜你喜欢
  • 2019-02-07
  • 2015-09-29
  • 2015-12-21
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
  • 2010-12-17
  • 2012-01-30
相关资源
最近更新 更多