ChatGPT解决这个技术问题 Extra ChatGPT

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

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


s
sashoalm

您可以在 SELECT 查询中使用 COLLATE NOCASE

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

此外,在 SQLite 中,您可以通过在列定义中指定 collate nocase(其他选项是 binary(默认值)和 rtrim;请参阅 here )。您也可以在创建索引时指定 collate nocase。例如:

create table Test
(
  Text_Value  text collate nocase
);

insert into Test values ('A');
insert into Test values ('b');
insert into Test values ('C');

create index Test_Text_Value_Index
  on Test (Text_Value collate nocase);

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

sqlite> select Text_Value from Test where Text_Value = 'B';
Text_Value      
----------------
b               

sqlite> select Text_Value from Test order by Text_Value;
Text_Value      
----------------
A               
b               
C    

sqlite> select Text_Value from Test order by Text_Value desc;
Text_Value      
----------------
C               
b               
A

优化器还可以潜在地利用索引在列上进行不区分大小写的搜索和匹配。您可以使用 explain SQL 命令检查这一点,例如:

sqlite> explain select Text_Value from Test where Text_Value = 'b';
addr              opcode          p1          p2          p3                               
----------------  --------------  ----------  ----------  ---------------------------------
0                 Goto            0           16                                           
1                 Integer         0           0                                            
2                 OpenRead        1           3           keyinfo(1,NOCASE)                
3                 SetNumColumns   1           2                                            
4                 String8         0           0           b                                
5                 IsNull          -1          14                                           
6                 MakeRecord      1           0           a                                
7                 MemStore        0           0                                            
8                 MoveGe          1           14                                           
9                 MemLoad         0           0                                            
10                IdxGE           1           14          +                                
11                Column          1           0                                            
12                Callback        1           0                                            
13                Next            1           9                                            
14                Close           1           0                                            
15                Halt            0           0                                            
16                Transaction     0           0                                            
17                VerifyCookie    0           4                                            
18                Goto            0           1                                            
19                Noop            0           0

在(重新)使用“COLLATE NOCASE”创建表之后,我注意到它比查询 WHERE name = 'someone' COLLATE NOCASE 快得多。快得多(大约 6 到 10 倍?)
根据文档,如果字段本身已经定义了以下排序规则,则不需要将 COLLATE NOCASE 添加到索引中:“The default collating sequence is the collating sequence defined for that column in the CREATE TABLE statement.
COLLATE NOCASE 仅适用于 ASCII 文本。一旦您的列值中有“FIANCÉ”或“voilà”,它就不会与“fiancé”或“VOILA”匹配。启用 ICU 扩展程序 LIKE becomes case-insensitive 后,'FIANCÉ' LIKE 'fiancé' 为真,但 'VOILA' LIKE 'voilà' 仍为假。 ICU+LIKE 的缺点是不使用索引,所以在大表上可能会很慢。
选择 div,case when div = 'fail' then 'FAIL' else 'PASSED' end,* from marking collate nocase 上面没有工作我做错了什么吗?
需要注意的一件事让我感到困惑:select * from tbl where firstname='john' and lastname='doe' COLLATE NOCASElastname 上将不区分大小写。要在 firstname 上不区分大小写,请写成:select * from tbl where firstname='john' COLLATE NOCASE and lastname='doe'。它特定于那一列,而不是整个 where 子句。
C
Craz
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

如果您像我一样想要更多关于整理的文档,您可以在此页面上找到它:sqlite.org/datatype3.html只需向下滚动到 #6.0
@will:现在是第 7 点,可通过 sqlite.org/datatype3.html#collating_sequences 直接访问
E
EJoshuaS - Stand with Ukraine

你可以这样做:

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

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

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


@MM-BB 是的,除非我们对声明(或索引)为 COLLATE NOCASE 的列执行 LIKE,否则它将对行进行完整扫描。
这不是错误,而是记录在案的限制。答案中引用的同一页面提到了管理 unicode 字符的 ICU 扩展。 (也许 2009 年并非如此)
如果您的搜索包含 %,这将产生意想不到的结果
@StevenPenny,是的,当然。 “LIKE”运算符进行模式匹配比较,我的回答中提到了这一点。
o
oscarkuo

这不是特定于 sqlite 的,但你可以这样做

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

性能问题的另一部分是在表中查找匹配的行。 SQLite3 是否支持基于函数的索引?在这种情况下索引搜索列或表达式(例如“UPPER(name)”)通常是一个好主意。
请注意这一点,正如 cheduardo 所暗示的,SQLite 在运行此查询时无法使用“名称”上的索引。 db 引擎将需要全扫描所有行,将所有“名称”字段转换为大写并运行比较。
这只是 ASCII - Jóga 之类的东西会失败
N
Nick Ericson

另一种选择是创建您自己的自定义排序规则。然后,您可以在列上设置该排序规则或将其添加到您的选择子句中。它将用于排序和比较。

这可以用来制作 'VOILA' LIKE 'voilà'。

http://www.sqlite.org/capi3ref.html#sqlite3_create_collation

如果第一个字符串分别小于、等于或大于第二个字符串,则整理函数必须返回一个负数、零或正数。


M
Magnus

在您的情况下可能有意义或可能没有意义的另一个选项是实际上有一个单独的列,其中包含现有列的预降分值。这可以使用 SQLite 函数 LOWER() 填充,然后您可以在此列上执行匹配。

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


C
Community

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


S
Shohel Rana

它完美地为我工作。 SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE


P
Pullat Junaid

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

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

在您发布此内容之前很久就已经回答了这个问题。
R
Rasel Khan

像这样使用

 "select * from $pwsXDataHistory where type = '$type' COLLATE NOCASE and $t_uStatus != '$DELETE' order by $t_name COLLATE NOCASE asc ");

M
Mahendranatarajan

您可以使用类似查询将相应的字符串与表值进行比较。

从 table_name 中选择列名,其中列名如“各自的比较值”;


这不会向 2009 年发布的 stackoverflow.com/a/973665/2462516 添加任何内容