【问题标题】:How can I prevent SQLite from treating a string as a number?如何防止 SQLite 将字符串视为数字?
【发布时间】:2013-03-14 18:32:10
【问题描述】:

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

类似问题

How do I prevent sqlite from evaluating a string as a math expression?

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


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

【问题讨论】:

  • 为我工作。 Path 列是如何定义的?
  • @CL。我很确定它被定义为 TEXT 列,但它现在不在我面前。明天我会检查并用比和 SQLite 版本号更新问题。
  • 我不确定这是否可行,但是像WHERE 'X' || Path &gt; 'X' || '/bravo/papa/' AND 'X' || '/bravo/papa0' 这样的东西呢?或者如果可能,首先将变量分配给'X' || Path 的值。
  • 我会试试的,虽然我不确定它是否仍能使用索引。但是,我已经在我的 Linux 笔记本电脑上尝试了查询,并且它的工作方式与我最初希望的 CL 一样。报告,所以我在 Windows 机器上的原始数据库肯定有其他问题。我明天更新。
  • 我也有这个问题。我所有的字符串列都被定义为 STRING 而不是 TEXT。工作正常,直到我尝试插入看起来像“1.4e-1”的东西,sqlite 愉快地变成了 0.14 。我希望 sqlite 引擎在声明不存在的类型(如 STRING)的亲和性时会引发某种异常。

标签: sqlite


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2012-08-18
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多