我对sqlite3有一个非常奇怪的问题 - 为windows运行sqlite3版本3.20.1。
两个不同表上的相同SELECT查询会生成不同的结果。但是列数据类型和数据在两者中都是相同的。以下是CREATE和INSERT语句。
CREATE TABLE key(key INTEGER UNIQUE NOT NULL);
CREATE TABLE map(key INTEGER UNIQUE NOT NULL, char TEXT);
WITH RECURSIVE cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt LIMIT 9999) INSERT INTO key(key) SELECT x FROM cnt WHERE x >=1000 ORDER BY random();
WITH RECURSIVE cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt LIMIT 9999) INSERT INTO map(key) SELECT x FROM cnt WHERE x >=1000 ORDER BY random();
这应该将随机排序的数字从1000到9999插入两列。但是,第二个表上的SELECT语句始终排序。结果如下
sqlite> SELECT key FROM map LIMIT 10;
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
sqlite> SELECT key FROM key LIMIT 10;
6165
1856
2457
2343
9095
8005
4958
4781
8334
1863
我甚至尝试了以下内容;
sqlite> DELETE FROM map;
sqlite> INSERT INTO map(key) SELECT key FROM key;
sqlite>
sqlite> SELECT key FROM map LIMIT 10;
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
它仍然排序!使用REPLACE也没有帮助。 我先尝试通过添加id列来改变表模式,但也没有成功。
经过一些实验后,我发现SELECT *
以正确的顺序显示了它,但SELECT key
给出了有序的结果。
sqlite> SELECT * FROM map LIMIT 10;
8418|
5869|
9753|
2886|
8354|
8244|
4063|
6692|
5440|
3508|
你能解释一下吗?这是一个错误还是一个功能?如何获得预期的输出?
答案 0 :(得分:0)
这应该将随机排序的数字从1000到9999插入两列。但是,第二个表上的SELECT语句始终排序。
你不了解SQL。 SQL表表示无序集。这意味着SQL引擎可以决定如何存储它想要的数据。
SQL查询返回无序集。这意味着SQL引擎可以决定结果集的顺序 - 除非您指定顺序。
在这种情况下,SQLite根据表中的唯一键返回结果集 - 它使用查询的索引。 (SQLite实际上可能正在决定唯一键是表的主键。)
答案 1 :(得分:0)
如果返回多行的SELECT语句没有ORDER BY子句,则返回行的顺序是未定义的。
如果您希望查询以随机顺序返回行,则必须在查询本身中使用ORDER BY random()
。
(要按内部顺序返回行,请使用ORDER BY rowid
,但这不适用于WITHOUT ROWID tables。)
UNIQUE约束的索引比表使用更少的存储,因为它只包含一列。 因此,只要您只想读取此列,查询优化器就会更喜欢直接从索引读取值(作为covering index),因为从磁盘读取较少的数据会使查询更快:
sqlite> EXPLAIN QUERY PLAN SELECT key FROM map;
0|0|0|SCAN TABLE map USING COVERING INDEX sqlite_autoindex_map_1
然后,返回的行恰好被排序只是副作用。