MySQL 整理子句 - 在 like 子句之前还是之后?
MySQL collate clause - before or after the like clause?
我正在努力将我们的数据库从 utf8 (utf8mb3) 移动到 utf8mb4(为最终移动到 MySQL 8 做准备),并且由于系统的性质以及数据库和主机的数量,我不能一次完成。所以,我试图弄清楚是否先迁移数据库(一次一个),然后应用程序才能正常工作。
在尝试的过程中,我 运行 遇到了以下情况,并希望就推荐的操作方式和原因征求专家意见。
MySQL 信息:
- 版本 - 5.7.30-33
- innodb_version - 5.7.30-33
- version_comment - Percona 服务器 (GPL),版本 33,修订版 6517692
- character_set_client - utf8
- character_set_connection - utf8
- character_set_database - utf8mb4
- collation_connection - utf8_general_ci
- collation_database - utf8mb4_general_ci
我有一个 table (show create table)
CREATE TABLE `mb4table1` (
`name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
具有价值
mysql> select * from mb4table1;
+------+------+
| name | age |
+------+------+
| abc | 43 |
| one | 41 |
| two | 42 |
+------+------+
3 rows in set (0.00 sec)
有了这个 table 和数据,
(1) 如果我执行查询
mysql> select * from mb4table1 where name like 'Abc';
Empty set (0.00 sec)
当然,它没有找到任何记录。
(2) 如果我这样做
mysql> select * from mb4table1 where name like 'Abc' collate utf8_general_ci;
+------+------+
| name | age |
+------+------+
| abc | 43 |
+------+------+
1 row in set (0.00 sec)
它能够找到 abc 的记录。
(3) 然而,如果我移动 collate 子句,
mysql> select * from mb4table1 where name collate utf8_general_ci like 'Abc';
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4'
(4) 而且,如果我使用 utf8mb4 归类,那么它工作正常
mysql> select * from mb4table1 where name collate utf8mb4_general_ci like 'Abc';
+------+------+
| name | age |
+------+------+
| abc | 43 |
+------+------+
1 row in set (0.00 sec)
我的问题是,(2) 和 (3) 有什么区别?查询 (2) 显然应用了 collate 子句并返回了预期结果。而且,如果我必须使用 (3),我该如何让它发挥作用?
注意:列排序规则必须保留。只有十分之二的查询可能需要使用 collate 子句来执行不区分大小写的搜索。
只要mysql不阻止它,我认为无论如何都不可能
您可以查看
SHOW COLLATION WHERE Charset = 'utf8mb4';
支持哪些排序规则
在https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html你可以看到所有的开头都有utf8mb4_
。
如果你想更深入。你可以从 https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html
开始
'Abc' collate utf8_general_ci
那个utf8_general_ci
属于没有uf8mb4(4字节)字符的字符串'Abc',可以安全地转换成那个cllation。
name collate utf8_general_ci
utf8_general_ci
属于 uf8mb4(4 字节)的列名并且 不能 转换为该排序规则,因为它不受支持(见上文) )
我正在努力将我们的数据库从 utf8 (utf8mb3) 移动到 utf8mb4(为最终移动到 MySQL 8 做准备),并且由于系统的性质以及数据库和主机的数量,我不能一次完成。所以,我试图弄清楚是否先迁移数据库(一次一个),然后应用程序才能正常工作。
在尝试的过程中,我 运行 遇到了以下情况,并希望就推荐的操作方式和原因征求专家意见。
MySQL 信息:
- 版本 - 5.7.30-33
- innodb_version - 5.7.30-33
- version_comment - Percona 服务器 (GPL),版本 33,修订版 6517692
- character_set_client - utf8
- character_set_connection - utf8
- character_set_database - utf8mb4
- collation_connection - utf8_general_ci
- collation_database - utf8mb4_general_ci
我有一个 table (show create table)
CREATE TABLE `mb4table1` (
`name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
具有价值
mysql> select * from mb4table1;
+------+------+
| name | age |
+------+------+
| abc | 43 |
| one | 41 |
| two | 42 |
+------+------+
3 rows in set (0.00 sec)
有了这个 table 和数据, (1) 如果我执行查询
mysql> select * from mb4table1 where name like 'Abc';
Empty set (0.00 sec)
当然,它没有找到任何记录。 (2) 如果我这样做
mysql> select * from mb4table1 where name like 'Abc' collate utf8_general_ci;
+------+------+
| name | age |
+------+------+
| abc | 43 |
+------+------+
1 row in set (0.00 sec)
它能够找到 abc 的记录。 (3) 然而,如果我移动 collate 子句,
mysql> select * from mb4table1 where name collate utf8_general_ci like 'Abc';
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4'
(4) 而且,如果我使用 utf8mb4 归类,那么它工作正常
mysql> select * from mb4table1 where name collate utf8mb4_general_ci like 'Abc';
+------+------+
| name | age |
+------+------+
| abc | 43 |
+------+------+
1 row in set (0.00 sec)
我的问题是,(2) 和 (3) 有什么区别?查询 (2) 显然应用了 collate 子句并返回了预期结果。而且,如果我必须使用 (3),我该如何让它发挥作用?
注意:列排序规则必须保留。只有十分之二的查询可能需要使用 collate 子句来执行不区分大小写的搜索。
只要mysql不阻止它,我认为无论如何都不可能
您可以查看
SHOW COLLATION WHERE Charset = 'utf8mb4';
支持哪些排序规则
在https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html你可以看到所有的开头都有utf8mb4_
。
如果你想更深入。你可以从 https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html
开始 'Abc' collate utf8_general_ci
那个utf8_general_ci
属于没有uf8mb4(4字节)字符的字符串'Abc',可以安全地转换成那个cllation。
name collate utf8_general_ci
utf8_general_ci
属于 uf8mb4(4 字节)的列名并且 不能 转换为该排序规则,因为它不受支持(见上文) )