18

我希望能够进行规范化重音字符的查询,例如:

é, è, and ê

在使用 '=' 和 'like' 的查询中都被视为 'e'。我有一排用户名字段设置为“ rené ”,我希望能够同时匹配“ rene ”和“ rené ”。

我试图用 MySQL 5.0.8 中的 'collat​​e' 子句来做到这一点。我收到以下错误:

mysql> select * from User where username = 'rené' collate utf8_general_ci;
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1'

FWIW,我的表是通过以下方式创建的:

CREATE TABLE `User` (
  `id` bigint(19) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniqueUsername` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=56790 DEFAULT CHARSET=utf8
4

5 回答 5

11

错误的原因不是表格,而是您输入的字符集,即查询中的“rené”。行为取决于character_set_connection变量:

用于没有字符集介绍器的文字和用于数字到字符串的转换的字符集。

使用 MySQL 客户端,使用以下命令进行更改SET NAMES

SET NAMES 'charset_name' 语句等效于以下三个语句:

SET character_set_client = charset_name;
SET character_set_results = charset_name;
SET character_set_connection = charset_name;

(来自http://dev.mysql.com/doc/refman/5.5/en/charset-connection.html

示例输出:

mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from User where username = 'rené' collate utf8_general_ci;
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1'

mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from User where username = 'rené' collate utf8_general_ci;
Empty set (0.00 sec)

或者, use 可以使用“字符集介绍器”显式设置字符集:

mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from User where username = _utf8'rené' collate utf8_general_ci;
Empty set (0.00 sec)

我知道这个问题已经很老了,但是由于谷歌把我带到这里来回答一个相关的问题,我虽然它仍然值得一个答案:)

于 2013-06-03T13:52:38.160 回答
7

我建议您将规范化版本与真实用户名一起保存到您的表中。即时更改编码可能会很昂贵,并且您必须在每次搜索时对每一行再次进行转换。

如果您使用的是 PHP,则可以使用iconv()来处理转换:

$username = 'rené';
$normalized = iconv('UTF-8', 'ASCII//TRANSLIT', $string);

然后您只需保存两个版本并使用规范化版本进行搜索并使用普通用户名进行显示。如果您还对搜索字符串进行规范化,则从规范化列进行比较和选择会更快:

$search = mysql_real_escape_string(iconv('UTF-8', 'ASCII//TRANSLIT', $_GET['search']));
mysql_query("SELECT * FROM User WHERE normalized LIKE '%".$search."%'");

当然,如果您有多个需要规范化的列,则此方法可能不可行,但在您的特定情况下,这可能会正常工作。

于 2010-02-20T16:34:10.840 回答
6

我已经在 MySQL 中实现了一个 strtr php 函数/tr unix 命令,你可以在这里获取源代码

您可以用作:

SELECT tr(name, 'áäèëî', 'aaeei') FROM persons

或剥离一些字符

SELECT tr(name, 'áäèëî', null) FROM persons
于 2012-10-22T23:58:58.523 回答
4
$normalized = iconv('UTF-8', 'ASCII//TRANSLIT', $string);

是一个完美的 php 解决方案,但在 mysql 中?兑换?

在mysql中

SELECT 'Álvaro José' as accented, (CONVERT ('Álvaro José' USING ascii)) as notaccented

生产:

Álvaro José     ?lvaro Jos?

重音词不会转换为无重音词,它不等同于 iconv 的音译。

RegExp 不适用于 UTF-8。

没有任何解决办法。

于 2011-05-20T15:21:30.873 回答
0

使用英文字符的搜索是否返回带有外文字符的结果?我编写了以下脚本来比较 MySQL 5.7 中的排序规则(也适用于 MariaDB 10.2+):

        $db->query('CREATE TABLE IF NOT EXISTS test (name varchar(20))
         Engine=InnoDB character set utf8mb4 collate utf8mb4_unicode_520_ci');

        $db->query('CREATE TABLE IF NOT EXISTS test2 (name varchar(20))
         Engine=InnoDB character set utf8mb4 collate utf8mb4_unicode_ci');

        $db->query("insert into test values('Łove 520')");
        $db->query("insert into test2 values('Łove 520')");

        $types = ['utf8mb4_unicode_520_ci', 'utf8mb4_unicode_ci'];
        $tables = ['test' => 'utf8mb4_unicode_520_ci', 'test2' => 'utf8mb4_unicode_ci'];
        foreach($types as $n)
        {
            foreach($tables as $ta => $tc)
            {
                $db->query("SET NAMES 'utf8mb4' COLLATE '$n'");
                $res = $db->query("Select * from $ta where name like 'Love%'"); // Ł equal
                echo "\ntable $ta($tc), names($n): ".$res->fetchColumn(0);
            }
        }

结果如下:

table test(utf8mb4_unicode_520_ci), names(utf8mb4_unicode_520_ci): Łove 520
table test2(utf8mb4_unicode_ci), names(utf8mb4_unicode_520_ci):
table test(utf8mb4_unicode_520_ci), names(utf8mb4_unicode_ci): Łove 520
table test2(utf8mb4_unicode_ci), names(utf8mb4_unicode_ci):

(注意:我从命令行运行脚本,所以它显示为 ┼üove 520 而不是 Łove 520)

当表排序规则为 utf8mb4_unicode_ 520 _ci 时,无论连接排序规则如何,似乎 L == Ł 。但是,如果您只使用 utf8mb4_unicode_ci ,它是不等价的。

于 2020-01-18T22:55:21.070 回答