如何在MySQL上进行SQL区分大小写的字符串比较?

Ste*_*enB 261 mysql sql interop case-sensitive string-comparison

我有一个函数返回五个字符混合大小写.如果我对这个字符串进行查询,它将返回值而不管大小写.

如何使MySQL字符串查询区分大小写?

Cra*_*ite 677

好消息是,如果你需要做一个区分大小写的查询,这是很容易做到:

SELECT *  FROM `table` WHERE BINARY `column` = 'value'
Run Code Online (Sandbox Code Playgroud)

  • 这正是我所寻找的.如果可以的话,我会更高.但问题是,这对性能有何影响?我在有限的报道中使用它,所以在我的情况下并不重要,但我很好奇. (31认同)
  • 为什么这不是答案?这正是我所需要的. (22认同)
  • 对于包含具有不同表示的相同字符的UTF-8字符串,这会做什么,例如使用组合字符来添加变音符号?这些UTF-8字符串可以被视为相等:`convert(char(0x65,0xcc,0x88)使用utf8)`(即`e`添加了`¨`)和`convert(char(0xc3,0xab)使用utf8) `(即`ë`),但添加'BINARY`将使它们不相等. (6认同)
  • @adjwilli如果列是索引的一部分,那么依赖于该索引的查询将受到性能损失.要保持性能,您需要实际更改表. (5认同)
  • 经过测试,这不适用于非ASCII字符,但可与COLLATE latin1_bin解决方案一起使用。 (2认同)
  • 作为一个性能示例:我的查询从3,5毫秒(可忽略不计)传递到1.570毫秒(这大约是一个半秒),查询的表包含约180万行。 (2认同)
  • 我推荐 @Nitesh 答案,因为性能优势(在值之前而不是在列之前使用 BINARY 关键字来启用索引)... `SELECT * FROM \`table\` WHERE \`column\` = BINARY 'value'` (2认同)

dru*_*dge 145

http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html

默认字符集和排序规则是latin1和latin1_swedish_ci,因此非二进制字符串比较默认情况下不区分大小写.这意味着如果使用col_name LIKE'a%'进行搜索,则会获得以A或a开头的所有列值.要使此搜索区分大小写,请确保其中一个操作数具有区分大小写或二进制排序规则.例如,如果要比较具有latin1字符集的列和字符串,则可以使用COLLATE运算符使任一操作数具有latin1_general_cs或latin1_bin排序规则:

col_name COLLATE latin1_general_cs LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_general_cs
col_name COLLATE latin1_bin LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_bin
Run Code Online (Sandbox Code Playgroud)

如果希望始终以区分大小写的方式处理列,请使用区分大小写或二进制排序规则来声明它.

  • @BT要使utf8列区分大小写,你可以使用bin colation如:`SELECT'mail'COLLATE utf8_bin ='Email' (27认同)
  • 如果您的列是utf-8编码,则不起作用 (5认同)
  • 关于如何在phpmyadmin中执行此操作的任何提示? (4认同)
  • @StevenB:点击列的编辑按钮,然后设置整理 - > http://i.imgur.com/7SoEw.png (4认同)
  • @StephaneEybert 如果您正在寻找直接区分大小写的问题,我很幸运在 ut8 表中的字段中使用 varbinary 而不是 varchar。HTH (2认同)

Nit*_*esh 43

克雷格怀特发布的答案,性能损失很大

SELECT *  FROM `table` WHERE BINARY `column` = 'value'
Run Code Online (Sandbox Code Playgroud)

因为它不使用索引.因此,您需要更改表格排序,如https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html所述.

要么

最简单的修复,您应该使用值的BINARY.

SELECT *  FROM `table` WHERE `column` = BINARY 'value'
Run Code Online (Sandbox Code Playgroud)

例如.

mysql> EXPLAIN SELECT * FROM temp1 WHERE BINARY col1 = "ABC" AND col2 = "DEF" ;
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | temp1  | ALL  | NULL          | NULL | NULL    | NULL | 190543 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
Run Code Online (Sandbox Code Playgroud)

VS

mysql> EXPLAIN SELECT * FROM temp1 WHERE col1 = BINARY "ABC" AND col2 = "DEF" ;
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                              |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
|  1 | SIMPLE      | temp1 | range | col1_2e9e898e | col1_2e9e898e | 93      | NULL |    2 | Using index condition; Using where |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
enter code here
Run Code Online (Sandbox Code Playgroud)

1排(0.00秒)

  • 我使用 Craig White 的解决方案已有一年,但在收到一些页面加载投诉后,我进行了更深入的研究,并进行了 Nitesh 建议的更改,查询时间从 2.5 秒缩短到 0.15 秒。当 Binary 在Where之前时,它没有使用索引。将 Binary 移动到使用索引的位置之后。谢谢你! (4认同)

小智 38

您可能希望使用LIKE或LIKE BINARY,而不是使用=运算符

// this returns 1 (true)
select 'A' like 'a'

// this returns 0 (false)
select 'A' like binary 'a'


select * from user where username like binary 'a'
Run Code Online (Sandbox Code Playgroud)

它的状态需要'a'而不是'A'


Pau*_*ler 27

在不更改被查询列的排序规则的情况下执行区分大小写的字符串比较的最正确方法是为要比较的列的值显式指定字符集和排序规则。

select * from `table` where `column` = convert('value' using utf8mb4) collate utf8mb4_bin;
Run Code Online (Sandbox Code Playgroud)

为什么不使用binary

不建议使用binary运算符,因为它比较编码字符串的实际字节。如果您比较使用不同字符集编码的两个字符串的实际字节数,则两个应该被视为相同的字符串可能不相等。例如,如果您有一个使用latin1字符集的列,并且您的服务器/会话字符集是utf8mb4,那么当您将该列与包含重音符号的字符串(例如 'café' )进行比较时,它将不匹配包含相同字符串的行!这是因为在latin1é 中被编码为字节,0xE9但在utf8其中是两个字节:0xC3A9.

为什么使用convert以及collate

排序规则必须与字符集匹配。因此,如果您的服务器或会话设置为使用latin1您必须使用的字符集,collate latin1_bin但如果您的字符集是utf8mb4您必须使用collate utf8mb4_bin. 因此,最可靠的解决方案是始终将值转换为最灵活的字符集,并对该字符集使用二进制排序规则。

为什么将convertandcollate应用于值而不是列?

当您在进行比较之前将任何转换函数应用于列时,它会阻止查询引擎使用索引(如果该列存在索引),这可能会大大减慢您的查询速度。因此,最好在可能的情况下转换该值。当在两个字符串值之间执行比较并且其中一个具有显式指定的排序规则时,查询引擎将使用显式排序规则,而不管它应用于哪个值。

口音敏感度

需要注意的是,MySql 不仅对使用_ci排序规则(通常是默认设置)的列不区分大小写,而且不区分重音。这意味着'é' = 'e'. 使用二进制排序规则(或binary运算符)将使字符串比较区分重音和大小写。

什么是utf8mb4

utf8MySql 中的字符集是最近版本中utf8mb3弃用的别名,因为它不支持 4 字节字符(这对于编码字符串很重要,如 )。如果您希望在MySql 中使用UTF8 字符编码,那么您应该使用utf8mb4字符集。


小智 16

要在使用BINARY之前使用索引,如果你有大表,你可以这样做.

SELECT
   *
FROM
   (SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
   BINARY `column` = 'value'
Run Code Online (Sandbox Code Playgroud)

子查询将导致一个非常小的不区分大小写的子集,然后您可以选择唯一区分大小写的匹配.


小智 8

以下是MySQL版本等于或高于5.5.

添加到/etc/mysql/my.cnf

  [mysqld]
  ...
  character-set-server=utf8
  collation-server=utf8_bin
  ...
Run Code Online (Sandbox Code Playgroud)

我尝试的所有其他排序规则似乎都不区分大小写,只有"utf8_bin"才有效.

不要忘记在此之后重启mysql:

   sudo service mysql restart
Run Code Online (Sandbox Code Playgroud)

根据http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html,还有一个"latin1_bin".

mysql启动不接受"utf8_general_cs".(我将"_cs"视为"区分大小写" - ???).


xie*_*fan 6

你可以像这样使用BINARY来区分大小写

select * from tb_app where BINARY android_package='com.Mtime';
Run Code Online (Sandbox Code Playgroud)

不幸的是,这个sql无法使用索引,您将在依赖于该索引的查询中遭受性能损失

mysql> explain select * from tb_app where BINARY android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | tb_app | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1590351 |   100.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
Run Code Online (Sandbox Code Playgroud)

幸运的是,我有一些技巧来解决这个问题

mysql> explain select * from tb_app where android_package='com.Mtime' and BINARY android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table  | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | tb_app | NULL       | ref  | idx_android_pkg           | idx_android_pkg           | 771     | const |    1 |   100.00 | Using index condition |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+  
Run Code Online (Sandbox Code Playgroud)