字符串比较时如何将Sqlite3设置为不区分大小写?
Posted
技术标签:
【中文标题】字符串比较时如何将Sqlite3设置为不区分大小写?【英文标题】:How to set Sqlite3 to be case insensitive when string comparing? 【发布时间】:2010-11-01 16:37:47 【问题描述】:我想通过字符串匹配从 sqlite3 数据库中选择记录。但是如果我在 where 子句中使用 '=',我发现 sqlite3 是区分大小写的。谁能告诉我如何使用不区分大小写的字符串比较?
【问题讨论】:
【参考方案1】:您可以在SELECT
查询中使用COLLATE NOCASE
:
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
另外,在 SQLite 中,您可以通过在列定义中指定 collate nocase
(其他选项为 binary
(默认值)和 rtrim
;参见here)。您也可以在创建索引时指定collate nocase
。例如:
涉及Test.Text_Value
的表达式现在应该不区分大小写。例如:
优化器还可以潜在地利用索引在列上进行不区分大小写的搜索和匹配。您可以使用explain
SQL 命令检查这一点,例如:
【讨论】:
使用“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的缺点是不使用索引,所以在大表上会很慢。
select div,case when div = 'fail' then 'FAIL' else 'PASSED' end,* from tags collate nocase above didn't work 我做错了什么吗?
有一点让我感到困惑: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
子句。【参考方案2】:
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
【讨论】:
如果你和我一样想要更多关于整理的文档,你可以在这个页面上找到它:sqlite.org/datatype3.html只需向下滚动到#6.0【参考方案3】:你可以这样做:
SELECT * FROM ... WHERE name LIKE 'someone'
(不是的解决方案,但在某些情况下很方便)
"LIKE 运算符执行一个模式 匹配比较。操作数 右边包含模式, 左侧操作数包含字符串 匹配模式。一种 模式中的百分号(“%”) 匹配任何零个或多个序列 字符串中的字符。一个 模式中的下划线(“_”) 匹配中的任何单个字符 细绳。 任何其他字符匹配 本身或其小写/大写 等效(即不区分大小写 匹配)。 (一个错误:仅限 SQLite 理解 ASCII 的大写/小写 人物。 LIKE 运算符是 case 对 unicode 字符敏感 超出 ASCII 范围。为了 例如,表达式 'a' LIKE 'A' 是 TRUE,但 'æ' LIKE 'Æ' 是 FALSE。)。”
【讨论】:
@MM-BB 是的,除非我们对声明(或索引)为 COLLATE NOCASE 的列执行 LIKE,否则它将对行进行全面扫描。 这不是一个错误,它是一个记录在案的限制。答案中引用的同一页面提到了管理 unicode 字符的 ICU 扩展。 (也许 2009 年并非如此) 如果您的搜索包含%
,这将产生意想不到的结果
@StevenPenny,是的,当然。 “LIKE”运算符会进行模式匹配比较,这在我的回答中有所提及。【参考方案4】:
这不是特定于 sqlite 的,但你可以这样做
SELECT * FROM ... WHERE UPPER(name) = UPPER('someone')
【讨论】:
性能问题的另一部分是在表中查找匹配的行。 SQLite3 是否支持基于函数的索引?在这种情况下索引搜索列或表达式(例如“UPPER(name)”)通常是个好主意。 小心这个,正如 cheduardo 所暗示的,SQLite 在运行这个查询时不能使用'name'上的索引。 db 引擎将需要全扫描所有行,将所有“名称”字段转换为大写并运行比较。 这只是 ASCII - 像Jóga
这样的东西会失败【参考方案5】:
另一种选择是创建您自己的自定义排序规则。然后,您可以在列上设置该排序规则或将其添加到您的选择子句中。它将用于排序和比较。
这可以用来制作 'VOILA' LIKE 'voilà'。
http://www.sqlite.org/capi3ref.html#sqlite3_create_collation
如果第一个字符串分别小于、等于或大于第二个字符串,则整理函数必须返回一个负数、零或正数。
【讨论】:
【参考方案6】:在您的情况下可能有意义或可能没有意义的另一个选项是实际上有一个单独的列,其中包含您现有列的预降分值。这可以使用 SQLite 函数LOWER()
填充,然后您可以在此列上执行匹配。
显然,它会增加冗余和潜在的不一致,但如果您的数据是静态的,它可能是一个合适的选择。
【讨论】:
【参考方案7】:如果列的类型为char
,那么您需要在查询的值后面加上空格,请参考这个问题here。这除了使用COLLATE NOCASE
或其他解决方案之一(upper() 等)。
【讨论】:
【参考方案8】:它非常适合我。
SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE
【讨论】:
【参考方案9】:简单地说,您可以在 SELECT 查询中使用 COLLATE NOCASE:
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
【讨论】:
在您发布此问题之前很久就已经回答了。【参考方案10】:这样使用
"select * from $pwsXDataHistory where type = '$type' COLLATE NOCASE and $t_uStatus != '$DELETE' order by $t_name COLLATE NOCASE asc ");
【讨论】:
【参考方案11】:您可以使用 like 查询将相应的字符串与表值进行比较。
从 table_name 中选择列名,其中列名类似于“各自的比较值”;
【讨论】:
这不会对 2009 年发布的 ***.com/a/973665/2462516 添加任何内容以上是关于字符串比较时如何将Sqlite3设置为不区分大小写?的主要内容,如果未能解决你的问题,请参考以下文章