sqlite查询返回有序区分大小写且不区分大小写的命中

时间:2016-11-04 02:18:30

标签: sql sqlite collation

让我们说我有一个包含单词表的数据库,如下所示:

CREATE TABLE Words (
  Id integer PRIMARY KEY NOT NULL,
  Word text NOT NULL
);
CREATE INDEX Word_Index ON Words (Word ASC);

sqlite> SELECT * FROM Words;
Id|Word
1|apple
2|Apple
3|Jack
4|jack

为了简单起见,我只想说我只关心ascii字符,只要区分大小写。

我想要做的是执行Word搜索并首先返回返回确切区分大小写匹配的行,然后返回匹配的所有行,忽略大小写,不重复。 例如,SELECT * FROM Words WHERE ...' Apple ' 会回来:

2|Apple
1|apple

同样,SELECT * FROM Words WHERE ...' apple ' 会回来:

1|apple
2|Apple

我主要关注区分大小写的匹配,但希望它们之后是不区分大小写的匹配,作为后备。我期待通常我会得到区分大小写的匹配,这就是为什么我有一个区分大小写的索引。我意识到不区分大小写的回退将无法使用索引,但我选择不使用第二个(COLLATE NOCASE)索引以节省数据库中的空间,因为它可能不经常使用。通常我只会踩到一次,抓住第一击。

最有效的方法是什么?

2 个答案:

答案 0 :(得分:2)

要使区分大小写和不区分大小写的搜索更有效,您需要两个索引:

CREATE INDEX Word_Index ON Words (Word);
CREATE INDEX Word_Index_nocase ON Words (Word COLLATE NOCASE);

当您使用ORDER BY进行操作时,无法使用有效的索引查找;您必须对区分大小写和不区分大小写的匹配执行单独的查找,并从第二个结果中筛选出重复项:

SELECT *
FROM Words
WHERE Word = 'Apple'

UNION ALL

SELECT *
FROM Words
WHERE Word COLLATE NOCASE = 'Apple'
  AND Word <> 'Apple';

(要处理非ASCII字符,您需要安装自定义排序规则。)

答案 1 :(得分:0)

我想你想要这样的东西:

SELECT *
FROM Words
WHERE LOWER(col) = LOWER('Apple')
ORDER BY (CASE WHEN col = 'Apple' THEN 1 ELSE 2 END),
         col;

默认情况下,SQLite区分大小写。

你可以尝试这个,但我不知道它是否会使用索引:

SELECT *
FROM Words
WHERE col = 'apple' COLLATE NO CASE
ORDER BY (CASE WHEN col = 'Apple' THEN 1 ELSE 2 END),
         col;