【问题标题】:SQLite database returning wrong minimum IDSQLite 数据库返回错误的最小 ID
【发布时间】:2022-01-03 20:23:52
【问题描述】:

我在 SQLite 数据库中遇到了一个相当奇怪的错误:当通过 ID 号对数据进行排序时,我返回的最小值远高于第二个(事实上,它甚至是最大值)。

我的要求是:

SELECT id FROM myTable ORDER BY id ASC LIMIT 10;

我的返回值是:

id
 1. 47196
 2. 14421
 3. 16419
 4. 16420 
 5. 16421 
 6. 16422 
 7. 16423 
 8. 16424 
 9. 16425 
 10. 16426

与“SELECT MIN(id) FROM myTable;”类似的结果,返回 47196

字段 id 定义为 INTEGER PRIMARY KEY。 我正在寻找根本原因。我的猜测是某种形式的损坏,但 SQLite 不会检测到数据库已损坏吗?

按照 Forpas 的想法,我尝试了:

SELECT id FROM myTable ORDER BY TRIM(id) + 0 ASC LIMIT 10;

这确实修复了结果,将 14421 放在首位。

我的 sqlite 版本是 3.6.19

如果有人能解释这意味着什么以及这些事情是如何发生的,我将不胜感激!

【问题讨论】:

  • 你确定 id 的数据类型是 int 吗?
  • 以防万一运行SELECT id FROM myTable ORDER BY TRIM(id) + 0 ASC LIMIT 10;的值中有前导空格@
  • 我猜你的 id 列包含文字,所以请尝试SELECT MIN(id), MIN(substr(id, INSTR(id, ' ')+1)) FROM myTable; sqlize.online/…
  • 由于 TRIM() 修复了问题,这意味着列值包含前导空格。将表格更新为:UPDATE myTable SET id = TRIM(id)

标签: sql sqlite


【解决方案1】:

字段 id 定义为 INTEGER。

如果有人能解释这意味着什么以及这些事情是如何发生的,我将不胜感激!

将列定义为 INTEGER 并不限制该列存储整数值。除了 rowid 列或其别名之外,任何列都可以存储可以存储的任何类型的值。

正是这种灵活性让你犯了错误。您将值保存为 TEXT 值,无意中引入了空格,因此在排序时会出现问题。

您不妨阅读Data Types in SQLite Version 3,其中包括:-

SQLite 版本 3 数据库中的任何列,除 INTEGER PRIMARY KEY 列外,都可用于存储任何存储类的值。

  • 请注意,不定义 INTEGER PRIMARY KEY 列实际上会导致额外的隐藏/特殊列,即 INTEGER PRIMARY KEY 列,即 rowid 列。使用 INTEGER PRIMARY KEY 使该列成为 rowid 列的别名(但不隐藏)。
    • 请注意,特别是 INTEGER PRIMARY KEY,即 INT PRIMARY KEY 不是 rowid 列的别名。
    • 除了 INTEGER PRIMARY KEY 之外,还可以使用 AUTOINCREMENT(请参阅上面有关 AUTOINCREMENT 的链接)

【讨论】:

  • 感谢您提供更多信息。但是,我的行 id 实际上是一个 INTEGER PRIMARY KEY。运行命令SELECT rowid FROM myTable 确实给出了与上面相同的结果,未修剪的 47196 首先出现。从 sqlite.org,我读到将非整数作为 PK 应该会产生“数据类型不匹配”并阻止操作。
  • @headdy 试试SELECT rowid, typeof(rowid) ....SELECT sql FROM sqlite_master where name = 'myTable';。第一个应将 47196 显示为整数。第二个用于创建表的sql。还有SELECT sqlite_version();
  • 第一个确实将 47196 显示为整数,第二个返回:CREATE TABLE myTable (id INTEGER PRIMARY KEY, GUID TEXT, DateTime INTEGER, PsetID INTEGER, TightCode1 TEXT, TightCode2 TEXT, TightCode3 TEXT, TightCode4 TEXT, Markup BLOB) 对于 sqlite 版本:3.6.19(不是最新版本,但不幸的是我无法升级它没有可靠的论据)
  • @headdy 我会假设它已损坏但未损坏到足以被检测到。我建议创建一个不是文件副本的副本,它相当于不可用(直到 3.15.0 才引入)VACUUM INTO。因此,也许附加一个空数据库并复制表等,然后检查是否可以解决问题。
猜你喜欢
  • 2019-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 1970-01-01
相关资源
最近更新 更多