我想查询一个包含目录路径的 SQLite 表,以查找某个层次结构下的所有路径。以下是列内容的示例:
/alpha/papa/
/alpha/papa/tango/
/alpha/quebec/
/bravo/papa/
/bravo/papa/uniform/
/charlie/quebec/tango/
如果我搜索下的所有内容/bravo/papa/
,我想得到:
/bravo/papa/
/bravo/papa/uniform/
我目前正在尝试这样做(请参阅下文,了解为什么我不能使用更简单的方法):
SELECT * FROM Files WHERE Path >= '/bravo/papa/' AND Path < '/bravo/papa0';
这行得通。它看起来有点奇怪,但它适用于这个例子。'0' 是大于 '/' 的 unicode 代码点 1。当按字典顺序排序时,所有以 '/bravo/papa/' 开头的路径都比较大于它和小于 'bravo/papa0'。但是,在我的测试中,我发现当我们尝试这样做时会出现这种情况:
SELECT * FROM Files WHERE Path >= '/' AND Path < '0';
这不返回任何结果,但它应该返回每一行。据我所知,问题在于 SQLite 将 '0' 视为数字,而不是字符串。例如,如果我使用“0Z”而不是“0”,我确实得到了结果,但我引入了获得误报的风险。(例如,如果实际上有一个条目“0”。)
我的问题的简单版本是:是否有某种方法可以让 SQLite 在这样的查询中将 '0' 视为包含 unicode 字符 '0' 的长度为 1 的字符串(它应该对字符串进行排序,例如 '!'、'* ' 和 '/',但在 '1'、'=' 和 'A' 之前)而不是整数 0(SQLite 在所有字符串之前排序)?
我认为在这种情况下,我实际上可以通过特殊情况搜索“/”下的所有内容,因为我的所有条目都将始终以“/”开头,但我真的很想知道如何避免这种事情一般来说,因为它与 Javascript 的 "==" 运算符一样令人不快。
第一种方法
更自然的方法是使用 LIKE 或 GLOB 运算符。例如:
SELECT * FROM Files WHERE Path LIKE @prefix || '%';
但我想支持所有有效的路径字符,所以我需要对 '_' 和 '%' 符号使用 ESCAPE。显然这会阻止 SQLite 在 Path 上使用索引。(请参阅http://www.sqlite.org/optoverview.html#like_opt)我真的希望能够从这里的索引中受益,这听起来像使用 LIKE 或 GLOB 是不可能的,除非我可以保证他们的任何一个目录名称中会出现特殊字符,POSIX 允许除 NUL 和 '/' 以外的任何字符,甚至 GLOB 的 '*' 和 '?' 人物。
我提供这个作为上下文。我对解决潜在问题的其他方法感兴趣,但我更愿意接受一个直接解决 SQLite 中看起来像数字的字符串的歧义的答案。
类似问题
在那个问题中,没有引用这些值。即使值被引用或作为参数传递,我也会得到这些结果。
编辑- 请参阅下面的答案。该列是使用无效类型“STRING”创建的,SQLite 将其视为 NUMERIC。