在stackoverflow的另一篇文章中,我读到INSTR
可用于按相关性排序结果。
我对col LIKE '%str%' and
INSTR(col,'str')`的理解是它们的行为都相同。处理排序规则似乎有所不同。
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO users (name)
VALUES ('Joël'), ('René');
SELECT * FROM users WHERE name LIKE '%joel%'; -- 1 record returned
SELECT * FROM users WHERE name LIKE '%rene%'; -- 1 record returned
SELECT * FROM users WHERE INSTR(name, 'joel') > 0; -- 0 records returned
SELECT * FROM users WHERE INSTR(name, 'rene') > 0; -- 0 records returned
SELECT * FROM users WHERE INSTR(name, 'joël') > 0; -- 1 record returned
SELECT * FROM users WHERE INSTR(name, 'rené') > 0; -- 1 record returned
虽然INSTR
进行了一些转换,但它会在ë
中找到é
。
SELECT INSTR('é', 'ë'), INSTR('é', 'e'), INSTR('e', 'ë');
-- returns 1, 0, 0
我错过了什么吗?
http://sqlfiddle.com/#!2/9bf21/6(使用mysql-version:5.5.22)
答案 0 :(得分:4)
这是由bug 70767 on LOCATE()
and INSTR()
引起的,已经过验证。
尽管INSTR()
文档指出它可用于多字节字符串,但正如您所注意到的那样,它似乎不适用于utf8_general_ci
这样的排序规则should be case and accent insensitive
此函数是多字节安全的,仅当至少一个参数是二进制字符串时才区分大小写。
错误报告指出虽然MySQL正确执行此操作,但只有当 bytes 的数量也相同时才会这样做:
但是,您可以轻松地观察到,当在另一个字符串中查找一个字符串时,他们不会(完全)尊重字典。似乎正在发生的事情是MySQL查找一个子字符串,该字符串是与目标完全相同的目标,其字节长度与目标完全相同。这很少是真的。
要隐藏报告示例,请创建下表:
create table t ( needle varchar(10), haystack varchar(10)
) COLLATE=utf8_general_ci;
insert into t values ("A", "a"), ("A", "XaX");
insert into t values ("A", "á"), ("A", "XáX");
insert into t values ("Á", "a"), ("Á", "XaX");
insert into t values ("Å", "á"), ("Å", "XáX");
然后运行此查询,您可以看到演示的相同行为:
select needle
, haystack
, needle=haystack as `=`
, haystack LIKE CONCAT('%',needle,'%') as `like`
, instr(needle, haystack) as `instr`
from t;