Oracle命令结果集没有order by子句

时间:2014-01-01 12:44:48

标签: sql oracle sql-order-by

有没有办法在没有实际使用“ORDER BY”子句的情况下从oracle表中获取“有序”结果集?

我正在开发一个从oracle表(没有唯一列)读取数据的应用程序,我想引入某种恢复机制,以便在查询失败的情况下(例如,在获取期间出现网络错误),我们避免读取行这已经取得了。

该应用程序是使用oracle OCI开发的,目前使用简单的选择查询。

有没有有效的机制来实现这个目标?

4 个答案:

答案 0 :(得分:1)

在某些非常特殊的情况下,您有一个已定义的结果顺序,而没有给出任何ORDER BY子句。但是,你不应该依赖它,Oracle可能随时改变这种行为。

也许您可以计算总行数(在执行查询后读取SQL%ROWCOUNT)并使用您客户端上收到的记录检查此数字。

答案 1 :(得分:0)

正如Wernfried指出的那样,没有可靠的方法来获得没有任何 ORDER BY的有序结果。但问题是假设ORDER BY是不可能的,因为没有唯一的列。至少有两种解决方法。

<强> 1。 ROWID。每个Oracle行都有一个唯一的伪列ROWID。该应用可以ORDER BY ROWID存储最新的ROWID,然后使用WHERE ROWID <= :rowid从中断的地方继续。请注意,如果表已被修改或移动,ROWIDs可能会发生变化。

<强> 2。 ROW_NUMBER。另一种选择是对所有数据进行排序并跟踪重复项。如果两行完全相同,那么返回和处理哪些重复项无关紧要。查询和应用程序只需跟踪已处理的数量。然后它可以在以后处理其余部分。

drop table test1;

create table test1(a number);
insert into test1 values(1);
insert into test1 values(1);
insert into test1 values(2);
commit;

select a ,row_number() over (order by a /*and all other columns*/) rowNumber
from test1
order by rowNumber

A  ROWNUMBER
1  1          --Am I the real #1?  It doesn't matter.
1  2
2  3

如果在第一行之后出现故障,则添加谓词where rownumber > :last_rownumber_processed将获得其余行。第二个查询可以返回“第一个”1而不是“第二个”1,但应用程序将不关心。与第一种解决方法一样,如果数据在运行之间发生变化,则会失败。

无论哪种方式,查询都必须支付排序费用:

----------------------------
| Id  | Operation          |
----------------------------
|   0 | SELECT STATEMENT   |
|   1 |  WINDOW SORT       |
|   2 |   TABLE ACCESS FULL|
----------------------------

答案 2 :(得分:0)

案例1:

为了实现简单的恢复机制,唯一简单的方法是使用RowID。

select t?.rowid, t1.*, t2.*, t3.* 
 from table1 t1, 
      table2 t2,
      table3 t3
where t1.? = t2.?
  and t2.? = t3.?
  and t?.rowid > :rowidProcessedPriorNetworkFailure
 order by t?.rowid 

t?.rowid的原因是因为你必须选择叶表。

在下列情况下你应该选择t3作为t?。 T2-T1:一个T2记录可能有一个或多个T1记录 T1-T3:一个T1记录可能有一个或多个T3记录

但请记住,只要Oracle维护底层物理结构(即defragmantation,Regorganization,将表移动到新数据文件),RowID就会改变。

案例2:

如果是连接,请选择叶表。 选择具有最不同值的列。按该列排序。每当你必须恢复时,用手头的最后一个值完成反向操作。

希望这会对你有所帮助。

答案 3 :(得分:-1)

我使用了以下查询来获取有序输出,而不使用&#34;命令&#34;话。在这里,我想在不使用order by子句的情况下对empno进行排序。

查询:

Select empno, sal, deptno, max(sal) over(partition by empno) from emp;

但是,您可以排除除empno和max()分析函数之外的所有列。

如果您有任何问题,请与我们联系。