# 10.14.4.1 使用 LDML 语法定义 UCA 归类

要在不重新编译 MySQL 的情况下为 Unicode 字符集添加 UCA 排序规则,请使用以下过程。如果您不熟悉用于描述归类排序特征的 LDML 规则,请参阅第 10.14.4.2 节,“MySQL 中支持的 LDML 语法”.

该示例添加了一个名为的排序规则utf8_phone_ciutf8字符集。排序规则是为涉及用户发布其姓名和电话号码的 Web 应用程序的场景而设计的。电话号码可以以非常不同的格式给出:

+7-12345-67
+7-12-345-67
+7 12 345 67
+7 (12) 345 67
+71234567

处理这些类型的值引发的问题是,不同的允许格式使得搜索特定电话号码变得非常困难。解决方案是定义一个新的排序规则,重新排序标点字符,使它们可以忽略。

  1. 选择一个排序规则ID,如图第 10.14.2 节,“选择归类 ID”.以下步骤使用 ID 1029。

  2. 要修改索引.xml配置文件。该文件位于由character_sets_dir系统变量。您可以按如下方式检查变量值,尽管您的系统上的路径名可能不同:

    mysql> SHOW VARIABLES LIKE 'character_sets_dir';
    +--------------------+-----------------------------------------+
    | Variable_name      | Value                                   |
    +--------------------+-----------------------------------------+
    | character_sets_dir | /user/local/mysql/share/mysql/charsets/ |
    +--------------------+-----------------------------------------+
    
  3. 为排序规则选择一个名称并将其列在索引.xml文件。此外,您需要提供排序规则。找出<字符集>要添加排序规则的字符集的元素,并添加一个<整理>指示排序规则名称和 ID 的元素,用于将名称与 ID 关联。内<整理>元素,提供一个<规则>包含排序规则的元素:

    <charset name="utf8">
      ...
      <collation name="utf8_phone_ci" id="1029">
        <rules>
          <reset>\u0000</reset>
          <i>\u0020</i> <!-- space -->
          <i>\u0028</i> <!-- left parenthesis -->
          <i>\u0029</i> <!-- right parenthesis -->
          <i>\u002B</i> <!-- plus -->
          <i>\u002D</i> <!-- hyphen -->
        </rules>
      </collation>
      ...
    </charset>
    
  4. 如果您想要其他 Unicode 字符集的类似排序规则,请添加其他<整理>元素。例如,要定义ucs2_phone_ci, 添加一个<整理>元素到<charset name="ucs2">元素。请记住,每个排序规则都必须有自己的唯一 ID。

  5. 重新启动服务器并使用此语句来验证排序规则是否存在:

    mysql> SHOW COLLATION WHERE Collation = 'utf8_phone_ci';
    +---------------+---------+------+---------+----------+---------+
    | Collation     | Charset | Id   | Default | Compiled | Sortlen |
    +---------------+---------+------+---------+----------+---------+
    | utf8_phone_ci | utf8    | 1029 |         |          |       8 |
    +---------------+---------+------+---------+----------+---------+
    

    现在测试排序规则以确保它具有所需的属性。

    使用新的排序规则创建一个包含一些示例电话号码的表:

mysql> CREATE TABLE phonebook (
         name VARCHAR(64),
         phone VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_phone_ci
       );
Query OK, 0 rows affected (0.09 sec)

mysql> INSERT INTO phonebook VALUES ('Svoj','+7 912 800 80 02');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Hf','+7 (912) 800 80 04');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Bar','+7-912-800-80-01');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Ramil','(7912) 800 80 03');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO phonebook VALUES ('Sanja','+380 (912) 8008005');
Query OK, 1 row affected (0.00 sec)

运行一些查询以查看忽略的标点字符是否实际上被忽略以进行比较和排序:

mysql> SELECT * FROM phonebook ORDER BY phone;
+-------+--------------------+
| name  | phone              |
+-------+--------------------+
| Sanja | +380 (912) 8008005 |
| Bar   | +7-912-800-80-01   |
| Svoj  | +7 912 800 80 02   |
| Ramil | (7912) 800 80 03   |
| Hf    | +7 (912) 800 80 04 |
+-------+--------------------+
5 rows in set (0.00 sec)

mysql> SELECT * FROM phonebook WHERE phone='+7(912)800-80-01';
+------+------------------+
| name | phone            |
+------+------------------+
| Bar  | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM phonebook WHERE phone='79128008001';
+------+------------------+
| name | phone            |
+------+------------------+
| Bar  | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM phonebook WHERE phone='7 9 1 2 8 0 0 8 0 0 1';
+------+------------------+
| name | phone            |
+------+------------------+
| Bar  | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)