像 MySQL 中的大小写敏感问题

40

我有一个MySQL查询:

SELECT concat_ws(title,description) as concatenated HAVING concatenated LIKE '%SearchTerm%';

我的表使用MyISAM编码为utf8_general_ci。

搜索似乎区分大小写。

我无法解决这个问题。出了什么问题,我该怎么修复它?


3
相关手册页面(仅限1个版本!)http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html - seanv507
8个回答

53

在性能方面更好的解决方案:

SELECT .... FROM .... WHERE `concatenated` LIKE BINARY '%SearchTerm%';

如果任何操作数是二进制字符串,则字符串比较区分大小写。

另一种选择是使用COLLATE

SELECT ....
FROM ....
WHERE `concatenated` like '%SearchTerm%' COLLATE utf8_bin;

4
我认为他希望搜索不区分大小写。 - Fuzzy76
11
没有二分查找是区分大小写的。二分查找是比较每个字符的二进制值,而不是它们所代表的字母。在非二进制比较中,"A" = "a",但在二进制比较中,"A" != "a",因为65 != 97。你把这个搞反了。然而,这对于那些寻找区分大小写搜索的人是有用的。 - Jouva Moufette
2
刚试了一下:SELECT 'a' LIKE 'A'; -- 1 ; SELECT 'a' LIKE BINARY 'A'; -- 0。所以二进制搜索是不区分大小写的。有异议吗? - kolypto
3
如果您看到大小写不敏感的结果,那么二进制应该是大小写敏感的。我怀疑如果您看到这样的结果,则测试用例可能存在问题。不过,如果MySQL开发人员做出这样卑鄙的事情,我也不会感到惊讶。 - Winfield Trail
2
@kolypto 为什么你的回答说“字符串比较是大小写敏感的”,而这里的评论说“二分查找是不区分大小写的”?正如你的例子所示,二分查找显然是区分大小写的。 - Naltharial
1
@Naltharial,:) 当然,只是混淆了术语。二进制字符串使比较区分大小写,这是肯定的。抱歉。 - kolypto

20

试试这个:

SELECT LOWER(CONCAT_WS(title,description)) AS concatenated 
WHERE concatenated LIKE '%searchterm%'

或者(让你看到区别)

SELECT LOWER(CONCAT_WS(title,description)) AS concatenated 
WHERE concatenated LIKE LOWER('%SearchTerm%')

尝试过了,仍然区分大小写。 - Pmc Machinery
@PmcMachinery:你看到我把你的LIKE部分改成小写字符串了吗? - Marco
是的,谢谢,我已经这样做了。当我这样做时,我也可以找到大写的“SearchTerms”。LOWER 似乎没有起到任何作用。 - Pmc Machinery
6
我已经理解了。看起来concat_ws会将结果转换为BLOB类型,而UPPER和LOWER无法在BLOB上运行。我通过添加CONVERT( ... USING utf8)来将BLOB转换为UTF8字符串,然后对其运行LOWER函数来解决这个问题。查询语句如下:SELECT LOWER(CONVERT(CONCAT_WS(title,description) USING utf8)) AS concatenated WHERE concatenated LIKE '%searchterm%'。 - Pmc Machinery

6
在这种方法中,您不必选择要搜索的字段:
SELECT table.id 
FROM table
WHERE LOWER(table.aTextField) LIKE LOWER('%SearchAnything%')

3
这个答案几乎两年前就已经发布了... 没有必要再做一遍。 - Ben

1

仅供参考,如果有帮助的话:

https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html所述,对于默认字符集,非二进制字符串比较默认不区分大小写。

因此,执行不区分大小写比较的简单方法是将字段转换为CHAR、VARCHAR或TEXT类型。

这里有一个针对单个字段的检查示例:

SELECT * FROM table1 WHERE CAST(`field1` AS CHAR) LIKE '%needle%';

1

检查表模式中提到的CHARSET:

show create table xyz;

根据字符集,您可以尝试以下操作。
select name from xyz where name like '%Man%' COLLATE latin1_bin;
select name from xyz where name like '%Man%' COLLATE utf8_bin;

以下是对我有效的情况,字符集为latin1,MySQL版本为5.6。

mysql> select installsrc from appuser where installsrc IS NOT NULL and installsrc like 'Promo%' collate latin1_bin limit 1;
+-----------------------+
| installsrc            |
+-----------------------+
| PromoBalance_SMS,null |
+-----------------------+
1 row in set (0.01 sec)

mysql>
mysql> select installsrc from appuser where installsrc IS NOT NULL and installsrc like 'PROMO%' collate latin1_bin limit 1;
+---------------------------+
| installsrc                |
+---------------------------+
| PROMO_SMS_MISSEDCALL,null |
+---------------------------+
1 row in set (0.00 sec)

mysql> select installsrc from appuser where installsrc IS NOT NULL and installsrc like 'PROMO%' limit 1;
+-----------------------+
| installsrc            |
+-----------------------+
| PromoBalance_SMS,null |
+-----------------------+
1 row in set (0.01 sec)

-1
这个问题在这种情况下发生是因为表中使用的排序规则。您使用了utf8_general_ci作为排序规则。如果将排序规则更改为utf8_general_ci,则搜索将不区分大小写。 因此,一个可能的解决方案是更改排序规则。

-2

这是可用的代码:

SELECT title,description
FROM (
 SELECT title,description, LOWER(CONCAT_WS(title,description)) AS concatenated
 FROM table1 
) AS Q
WHERE concatenated LIKE LOWER('%search%') 

-2

这个也可以运行:

SELECT LOWER(DisplayName) as DN
FROM   Bidders
WHERE  OrgID=45
HAVING DN like "cbbautos%"
LIMIT  10;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接