同一SQL查询返回不同结果集但行数相同的原因咨询
问题分析:临时表查询结果顺序变化但行数一致的原因
先帮你格式化一下SQL语句,方便梳理细节:
CREATE TABLE #TEMP( CID INT, PID INT, STAT VARCHAR(20), TIN DATETIME, TOUT DATETIME ) INSERT INTO #TEMP(CID, STAT, PID, TIN, TOUT) SELECT DISTINCT CID, STST, PID, TIN, TOUT FROM CVTBL WHERE STAT = 'YES' AND PID = '12' ORDER BY CID DESC; SELECT * FROM #temp; DROP TABLE #temp;
你遇到的现象——每次查询#temp结果看似内容不同但行数完全一致,核心原因是临时表默认是堆表(Heap),没有固定的排序规则,数据库返回结果的顺序是不确定的,具体拆解如下:
堆表的存储特性:临时表创建时如果没指定
CLUSTERED INDEX或PRIMARY KEY(后者默认会生成聚集索引),它就是一个堆表。堆表的数据按数据页的分配顺序存储,没有固定的逻辑排序。执行SELECT * FROM #temp时,数据库会直接扫描堆的物理页,而页的读取顺序可能因缓存状态、数据库内部页分配策略、查询优化器的微小调整发生变化,导致行的返回顺序不同,但实际是同一批数据。INSERT时的ORDER BY不持久:你在插入临时表时用了ORDER BY CID DESC,但这个排序只作用于插入过程,不会让堆表始终保持这个顺序。堆表不会维护插入顺序,后续无ORDER BY的查询依然会按物理存储的页顺序返回,所以插入时的排序对后续查询没有持久影响。排除数据变更的可能:因为行数始终一致,基本可以排除
CVTBL在你执行这段SQL期间有数据插入/删除的情况——如果是数据变更,行数大概率会出现波动。
解决办法
如果希望每次查询返回的顺序完全一致,有两种简单方案:
- 查询临时表时加上明确的
ORDER BY:
SELECT * FROM #temp ORDER BY CID DESC;
- 创建临时表时直接定义聚集索引固定顺序:
CREATE TABLE #TEMP( CID INT, PID INT, STAT VARCHAR(20), TIN DATETIME, TOUT DATETIME, PRIMARY KEY CLUSTERED (CID DESC) )
内容的提问来源于stack exchange,提问作者Jiah
相关产品推荐
相关产品推荐

