3

我想在我的数据库中搜索通常包含许多特殊字符的波兰城市。我想将它们迁移到 ASCII,这样即使没有波兰语键盘的人也可以进行常规搜索。

在 PHP 中看起来像

$ascii = iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $text);

但是如何在 mysql 选择查询中实现呢?

select * from city where CONVERT(city using ASCII)=CONVERT(? using ASCII)

不起作用,因为它用问号替换所有未知字符

select CONVERT('Lódź' using ascii );
-- RESULT: L?d?
4

3 回答 3

1

操作员行为

等号运算符=

如果您使用等号运算符=进行精确搜索,则解决方案@rsanchez是正确的。例如,找到等于的行œ可以使用这个精确值œ或其音译值来完成oe

SELECT 'œ' = 'oe' COLLATE utf8_unicode_ci ;
-- true
+-------------------------------------+
| 'œ' = 'oe' COLLATE utf8_unicode_ci  |
+-------------------------------------+
|                                   1 |
+-------------------------------------+

将返回等于œoe如果用户使用其中任何一个的行。

LIKE操作员

但是,如果您想使用LIKEoperator进行模糊搜索,这是行不通的。例如,œ通过键入oe搜索包含的单词将不会返回带有œ.

SELECT 'œ' LIKE 'oe' COLLATE utf8_unicode_ci ;
-- false
+----------------------------------------+
| 'œ' LIKE 'oe' COLLATE utf8_unicode_ci  |
+----------------------------------------+
|                                      0 |
+----------------------------------------+

解释 ?

这不是错误,而是SQL 标准的预期行为(参见 Alexander Barkov 的回答),就像在使用更复杂的方法(例如,允许音译相等)LIKE时基于字符进行比较一样。=

解决方案

提供音译形式

一种解决方案是生成搜索的音译并修改查询以搜索每种形式:

SELECT * FROM `mytable` 
  WHERE `myfield` LIKE 'oe' or `myfield` LIKE 'oe' 
COLLATE  utf8_unicode_ci;

使用全文搜索

MySQL 5.6 开始,全文搜索现在可用于 InnoDB(以前它仅可用于MyISAM表)。

于 2014-03-06T12:10:51.633 回答
1

本答案中所述,如果您使用排序规则utf8_general_ci,则字符串比较将不区分大小写和重音,因此在执行查询时无需指定任何转换:

CREATE TABLE test (name varchar(100)) COLLATE 'utf8_general_ci';
INSERT test (name) VALUES ('Lódź');

SELECT * FROM test WHERE name = 'Lodz';

name
----
Lódź

在这里提琴

如果你想为你的列指定另一个排序规则,你甚至可以在一个特定的查询中应用这个排序规则:

CREATE TABLE test (name varchar(100)) COLLATE 'utf8_polish_ci';
INSERT test (name) VALUES ('Lódź');


SELECT * FROM test WHERE name = 'Lodz';

Empty set (0.00 sec)


SELECT * FROM test WHERE name COLLATE 'utf8_general_ci' = 'Lodz';

name
----
Lódź

第二小提琴在这里

于 2013-09-30T13:07:07.300 回答
0

迟到了,但我的回答是:

CREATE FUNCTION TO_ASCII(
    text_to_replace MEDIUMTEXT
) RETURNS MEDIUMTEXT
BEGIN
    DECLARE i INT;
    DECLARE char_from, char_to VARCHAR(50);

    SET char_from := 'ĄĆĘŁŃÓŚŻŹąćęłńóśżź ';
    SET char_to   := 'ASCZZEOLNasczzeoln_';
    SET i := CHAR_LENGTH(char_from);

    WHILE i
        DO
            SET text_to_replace := REPLACE(text_to_replace, SUBSTR(char_from, i, 1), SUBSTR(char_to, i, 1));
            SET i:= i - 1;
        END WHILE;

    RETURN text_to_replace;
END;

和用法:

SELECT TO_ASCII('abcąśćó   ĄĆĘŁŃÓŚŻŹąćęłńóśżź  ĄĆĘŁŃÓŚŻŹąćęłńóśżź ');
于 2020-10-31T20:03:52.423 回答