【问题标题】:Using ICONV on mysql select - transform all characters to standard ascii在 mysql select 上使用 ICONV - 将所有字符转换为标准 ascii
【发布时间】:2013-02-20 09:43:15
【问题描述】:

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

在 PHP 中看起来像

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

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

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

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

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

【问题讨论】:

  • 除了这种转换是猜测之外,是否为最终用户提供虚拟键盘?
  • mh 当然可以,但是这个搜索是在 API 端,它将被移动应用程序使用。除此之外,允许两个字符或多或少被认为是用户友好的
  • 当然我可以使用 str_replace gist.github.com/mlaug/030889328263b5144b72 但也许有更易读和更自信的方式
  • 您使用什么字符集和排序规则来存储城市名称?

标签: mysql character-encoding ascii iconv transliteration


【解决方案1】:

this answer 中所述,如果您使用排序规则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ź

Fiddle here

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

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ź

Second fiddle here

【讨论】:

    【解决方案2】:

    操作员行为

    等号运算符=

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

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

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

    LIKE运营商

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

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

    解释?

    这不是一个错误,但 expected behavior by SQL standard (see Alexander Barkov answer)LIKE 是在字符基础上进行比较,而 = 使用更复杂的方法(例如允许音译相等)。

    解决方案

    提供音译形式

    一种解决方案是生成搜索的音译并修改您的查询以搜索每个表单:

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

    使用全文搜索

    由于MySQL 5.6, fulltext search现在可用于 InnoDB(以前它仅可用于 MyISAM 表)。

    【讨论】:

      【解决方案3】:

      迟到了,但我的回答是:

      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ąśćó   ĄĆĘŁŃÓŚŻŹąćęłńóśżź  ĄĆĘŁŃÓŚŻŹąćęłńóśżź ');
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-31
        • 2010-12-30
        相关资源
        最近更新 更多