字符串比较时如何将Sqlite3设置为不区分大小写?


305

我想通过字符串匹配从sqlite3数据库中选择记录。但是,如果我在where子句中使用'=',我发现sqlite3区分大小写。谁能告诉我如何使用不区分大小写的字符串比较?

Answers:


493

您可以COLLATE NOCASESELECT查询中使用:

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

另外,在SQLite中,您可以通过collate nocase在列定义中指定(其他选项为binary(默认)和rtrim;参见此处)来指示在创建表时该列不区分大小写。您还可以指定collate nocase何时创建索引。例如:

创建表测试
(
  Text_Value文本不区分大小写
);

插入测试值('A');
插入测试值(“ b”);
插入测试值(“ C”);

创建索引Test_Text_Value_Index
  在测试(Text_Value整理无大小写);

Test.Text_Value现在,涉及的表达式应该不区分大小写。例如:

sqlite>从Test中选择Text_Value,其中Text_Value ='B';
文字值      
----------------
b               

sqlite>从测试顺序中选择Text_Value通过Text_Value;
文字值      
----------------
一个               
b               
C    

sqlite>从测试顺序中按Text_Value desc选择Text_Value;
文字值      
----------------
C               
b               
一个               

优化程序还可以潜在地利用索引进行不区分大小写的列搜索和匹配。您可以使用explainSQL命令进行检查,例如:

sqlite>解释一下,从Test中选择Text_Value,其中Text_Value ='b';
addr操作码p1 p2 p3                               
---------------- -------------- ---------- ---------- ---------------------------------
0转到0 16                                           
1整数0 0                                            
2 OpenRead 1 3 keyinfo(1,NOCASE)                
3 SetNumColumns 1 2                                            
4字符串8 0 0 b                                
5 IsNull -1 14                                           
6 MakeRecord 1 0 a                                
7存储器0 0                                            
8 MoveGe 1 14                                           
9内存加载0 0                                            
10 IdxGE 1 14 +                                
11栏1 0                                            
12回叫1 0                                            
13下一个1 9                                            
14关闭1 0                                            
15暂停0 0                                            
16交易0 0                                            
17 VerifyCookie 0 4                                            
18转到0 1                                            
19 Noop 0 0                                            

20
之后(重新)创建与“COLLATE NOCASE”的表,我发现这是很多比查询速度更快,其中name =“有人” COLLATE NOCASE。速度更快(大概是6到10倍?)
DefenestrationDay 2011年

10
根据文档,COLLATE NOCASE如果字段本身已经定义了此排序规则,则无需添加到索引:“ 默认的排序顺序是在CREATE TABLE语句中为该列定义的排序顺序。
Heinzi 2012年

29
COLLATE NOCASE仅适用于ASCII文本。列值中一旦包含“FIANCÉ”或“voilà”,就不会与“fiancé”或“ VOILA”匹配。启用ICU扩展后,LIKE变为不区分大小写,这'FIANCÉ' LIKE 'fiancé'是true,但'VOILA' LIKE 'voilà'仍然是false。而且ICU + LIKE的缺点是不使用索引,因此在大表上速度可能很慢。

选择div,如果div ='fail',然后'FAIL',否则'PASSED'结尾,*从上面的标记整理nocase无效,我在做错什么吗?
2014年

7
需要注意的一件事使我绊倒了:在select * from tbl where firstname='john' and lastname='doe' COLLATE NOCASE上将不区分大小写lastname。要不区分大小写firstname,请输入:select * from tbl where firstname='john' COLLATE NOCASE and lastname='doe'。它特定于那一列,而不是整个where子句。
James Toomey

148
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

5
如果你和我一样,想在整理更多的文档,你可以在这里找到这个页面上:sqlite.org/datatype3.html 只是向下滚动到#6.0
威尔

47

您可以这样做:

SELECT * FROM ... WHERE name LIKE 'someone'

(这不是解决办法,但在某些情况下是非常方便)

LIKE运算符进行模式匹配比较。右侧的操作数包含模式,左侧的操作数包含要与模式匹配的字符串。模式中的百分号(“%”)匹配零或更大的任何序列字符串中的字符。模式中的下划线(“ _”)匹配字符串中的任何单个字符。其他任何字符都匹配 自身或其 等效的大小写不区分大小写(错误:SQLite仅理解ASCII字符的大写/小写LIKE运算符对ASCII范围之外的Unicode字符区分大小写,例如,表达式'a'LIKE'A'为TRUE,但'æ'LIKE'Æ'是FALSE。”。


@ MM-BB是的,除非我们对声明(或索引)为COLLATE NOCASE的列执行LIKE,否则它将对行进行完整扫描。
尼克·丹杜拉基斯

1
这不是错误,而是有记录的限制。答案中引用的同一页提到管理Unicode字符的ICU扩展。(也许不是2009年的情况)
stenci

40

这不是特定于sqlite,但您可以做

SELECT * FROM ... WHERE UPPER(name) = UPPER('someone')

性能问题的另一部分是在表中找到匹配的行。SQLite3是否支持基于函数的索引?在这种情况下索引搜索列或表达式(例如“ UPPER(name)”)通常是一个好主意。
cheduardo

13
正如cheduardo所暗示的那样,请小心使用它,SQLite在运行此查询时无法使用'name'上的索引。数据库引擎将需要完全扫描所有行,将所有“名称”字段都转换为大写并运行比较。
Mathew Waters 2012年

1
@数量,是的,很多。
贝尔加


2

在您的情况下可能有意义的另一种选择是,实际上是使用现有列的前低下分数的单独列。可以使用SQLite函数填充LOWER()该字段,然后可以在此列上执行匹配。

显然,它增加了冗余并可能导致不一致,但是如果您的数据是静态的,则可能是合适的选择。


2

简单来说,您可以在SELECT查询中使用COLLATE NOCASE:

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

1

如果该列是类型的,char那么您需要在查询的值后面加上空格,请在此处参考此问题。除了使用COLLATE NOCASE或其他解决方案之一(upper()等)之外。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.