有没有办法在没有实际使用“ORDER BY”子句的情况下从oracle表中获取“有序”结果集?
我正在开发一个从oracle表(没有唯一列)读取数据的应用程序,我想引入某种恢复机制,以便在查询失败的情况下(例如,在获取期间出现网络错误),我们避免读取行这已经取得了。
该应用程序是使用oracle OCI开发的,目前使用简单的选择查询。
有没有有效的机制来实现这个目标?
答案 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()
分析函数之外的所有列。
如果您有任何问题,请与我们联系。