查询结果的排序问题


一个项目最近数据库从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来排序


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3