7

我想查询一个包含目录路径的 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 中看起来像数字的字符串的歧义的答案。

类似问题

如何防止 sqlite 将字符串评估为数学表达式?

在那个问题中,没有引用这些值。即使值被引用或作为参数传递,我也会得到这些结果。


编辑- 请参阅下面的答案。该列是使用无效类型“STRING”创建的,SQLite 将其视为 NUMERIC。

4

1 回答 1

6

*呻吟*。该列具有 NUMERIC 相关性,因为它被意外指定为“STRING”而不是“TEXT”。由于 SQLite 无法识别类型名称,因此将其设为 NUMERIC,并且由于 SQLite 不强制列类型,所以其他一切都按预期工作,除了任何时候将类似数字的字符串插入该列时,它都会转换为数字类型。

于 2013-03-14T09:14:15.023 回答