一个项目最近数据库从oracle9i迁移到了10g(imp和exp),一个同事最近反映过来一个问题,说一个schedulertask表的查询结果在迁移前是有序的,迁移过来后,就变成无序状态了。
我进行了如下测试:
原查询语句:
select distinct to_char(starttime,'yyyy-mm') from schedulertask;
查询结果:
TO_CHAR
-------
2006-09
2006-10
2008-12
2007-10
2008-03
2009-06
2009-04
2007-09
2009-03
2006-06
2007-07
2007-04
2007-08
2007-01
2007-06
2007-11
2009-01
2009-07
2006-01
2006-05
2006-12
2007-05
2008-02
2006-02
2006-03
2006-04
2006-07
2007-03
2008-11
2008-06
2008-07
2008-10
2009-05
2009-02
2008-05
2006-11
2008-01
2008-09
2008-04
2007-12
2006-08
2007-02
2008-08
已选择43行。
----果然是无序的,但是多次查询的结果却是一致的。
开始认为是这个表没有主键,把表中的SCHEDULERTASKID字段加上了not null约束,作为主键,再查询,还是不行。
继续分析,感觉可能是这样:oracle的查询语句应该是这么工作的,首先从数据文件中按照数据的存取顺序读出查询的数据,如果没有order by子句,查询到的结果立即以数据的组织顺序给出,如果带order by子句,会在临时表空间中进行一次排序,再把排序后的结果给出。对于迁移前后的结果不一致,我想迁移前的数据的存放是有序的,迁移后由于种种原因,数据的存放顺序发生了改变。
从SQL语言编写的角度来讲,希望得到有序的查询结果,最好还是加上order by子句。
所以建议,将原来的查询语句修改成:
select distinct to_char(starttime,'YYYY-MM') starttime from schedulertask order by starttime;或者
select distinct to_char(starttime,'YYYY-MM') AS starttime from schedulertask order by starttime;
得到的结果就有序了:
STARTTI
-------
2006-01
2006-02
2006-03
2006-04
2006-05
2006-06
2006-07
2006-08
2006-09
2006-10
2006-11
2006-12
2007-01
2007-02
2007-03
2007-04
2007-05
2007-06
2007-07
2007-08
2007-09
2007-10
2007-11
2007-12
2008-01
2008-02
2008-03
2008-04
2008-05
2008-06
2008-07
2008-08
2008-09
2008-10
2008-11
2008-12
2009-01
2009-02
2009-03
2009-04
2009-05
2009-06
2009-07
在测试这个简单的语句时,也发生了一些有趣的现象:
SQL> select distinct to_char(starttime,'yyyy-mm') from schedulertask order by starttime;
select distinct to_char(starttime,'yyyy-mm') from schedulertask order by starttime
*
第 1 行出现错误:
ORA-01791: 不是 SELECTed 表达式
SQL> select distinct to_char(starttime,'yyyy-mm') from schedulertask order by SCHEDULERTASKID;
select distinct to_char(starttime,'yyyy-mm') from schedulertask order by SCHEDULERTASKID
*
第 1 行出现错误:
ORA-01791: 不是 SELECTed 表达式
原因分析:
在普通的查询语句,order by后跟的字段只要是表中存在的字段,都是ok的,这里之所以跟starttime和SCHEDULERTASKID都报错,是因为在select子句中,如果带有distinct关键字,就只能以查询的对象字段作为排序标准,同时,starttime在经过to_char转换后,就不再是starttime了,所以我们还得给它取个别名“starttime”,然后再根据starttime来排序。
阅读(757) | 评论(0) | 转发(0) |