我希望能够进行规范化重音字符的查询,例如:
é, è, and ê
在使用'='和'like'的查询中,都被视为'e'。我的用户名字段设置为“rené”,我希望能够将其与“ rene ”和“rené”匹配”。
我试图用MySQL 5.0.8中的'collate'子句来做这件事。我收到以下错误:
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
答案 0 :(得分:9)
错误的原因不是表格,而是输入的字符集,即查询中的“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)
我知道这个问题已经很老了但是由于谷歌带我来这里提出相关问题,我还是应该得到一个答案:)
答案 1 :(得分: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."%'");
当然,如果您有多个需要规范化的列,则此方法可能不可行,但在您的特定情况下,这可能正常工作。
答案 2 :(得分:5)
我在MySQL中实现了一个strtr php function / tr unix命令,你可以得到源here
您可以使用as:
SELECT tr(name, 'áäèëî', 'aaeei') FROM persons
或删除一些字符
SELECT tr(name, 'áäèëî', null) FROM persons
答案 3 :(得分:3)
$normalized = iconv('UTF-8', 'ASCII//TRANSLIT', $string);
是一个完美的PHP解决方案,但在mysql? CONVERT?
在mysql中
SELECT 'Álvaro José' as accented, (CONVERT ('Álvaro José' USING ascii)) as notaccented
农产品:
Álvaro José ?lvaro Jos?
重音词不会转换为无重音词,也不等同于iconv的转换。
RegExp不适用于UTF-8。
没有任何解决方案。
答案 4 :(得分: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):
(注意:我是从命令行运行脚本的,所以它显示为┼üove520而不是Łove520)
当表排序规则为utf8mb4_unicode_ 520 _ci时,似乎L ==Ł,无论连接排序规则如何。但是,如果仅使用utf8mb4_unicode_ci,则不等效。