在下面的示例中,我是否总是得到“1,2”,或者是否可以获得“2,1”并且您能告诉我您在文档中的哪个位置可以保证它是否存在?
如果答案是肯定的,则意味着没有ORDER BY
或ORDER SIBLINGS
,就可以确定SELECT语句中的结果集顺序。
CREATE TYPE temp_row IS OBJECT(x number);
/
CREATE TYPE temp_table IS TABLE OF temp_row;
/
CREATE FUNCTION temp_func
RETURN temp_table PIPELINED
IS
BEGIN
PIPE ROW(temp_row(1));
PIPE ROW(temp_row(2));
END;
/
SELECT * FROM table(temp_func());
谢谢。
答案 0 :(得分:5)
我不认为文档中的任何地方保证将返回数据的顺序。
2003年有一个旧的Tom Kyte thread(所以可能已过期),这表明依赖隐含的顺序是不可取的,原因与您不依赖的原因相同在普通SQL中的顺序。
1st:是表函数返回的行的顺序 SQL语句与条目“管道”完全相同的顺序 进入内部集合(这样就不需要order by子句)?
...
跟进2003年5月18日 - 上午10点UTC:
1)也许,也许不是,我不会指望它。你不应该数 在没有订单的结果集中的行的顺序。如果 你加入或做一些更复杂的事情,然后简单地“选择*来自 table(f(x))“,行可以以其他顺序返回。
经验证明 - 他们似乎是在用管道输回的时候回来的。我不 相信这是记录在案的。实际上,NESTED TABLE类型的集合是明确记录的 无法保留订单。
为了安全起见,如果您希望查询结果是有序的话,您应该像在查询中一样,做一个显式的ORDER BY。
说过我已经完成了你的功能并运行了1000万次迭代,以检查隐式顺序是否曾被破坏;事实并非如此。
SQL> begin
2 for i in 1 .. 10000000 loop
3 for j in ( SELECT a.*, rownum as rnum FROM table(temp_func()) a ) loop
4
5 if j.x <> j.rnum then
6 raise_application_error(-20000,'It broke');
7 end if;
8 end loop;
9 end loop;
10 end;
11 /
PL/SQL procedure successfully completed.
答案 1 :(得分:1)
此过程逻辑与基于表的查询的工作方式不同。您不能依赖表中的select中的订单的原因是您不能依赖RDBMS将行标识为所需集的一部分的顺序。部分原因是执行计划发生变化,部分原因是表中行的物理顺序可预测的情况非常少。
但是,您可以从一个函数中进行选择,该函数确保从函数中发出行的顺序。在没有连接,聚合或其他任何东西的情况下(即直接“从表(函数)中选择...”)我会非常肯定行顺序是确定性的。
除非存在明确的order-by,否则该建议不适用于涉及表的情况,因此如果从不使用order-by的查询加载pl / sql集合,那么当然是行的顺序在集合中不是确定性的。
答案 2 :(得分:0)
目前接受的答案中的AskTom链接已断开,但我发现newer yet very similar question。经过一番“误会”之后,康纳·麦克唐纳最终承认在某些情况下该顺序是稳定的,包括并行性和ref游标,并且仅与当前版本有关。引用:
平行主义是这里的(潜在)风险。 就目前而言,流水线函数只有在将ref游标作为输入的情况下才能并行运行。当然不能保证将来不会改变。 因此,您可以在 current 版本中的假定上运行,您将按顺序重新获得行,但是您永远不可能100%依赖这种情况,而且永远不会更多
因此不能保证将来的版本。
有问题的函数将通过此标准,因此应提供稳定的顺序。但是,我个人不会信任它。我的情况(当我发现这个问题时)更加简单:从字面指定的集合中进行选择-select column_value from table(my_collection(5,3,7,2))
,并且无论如何,我还是倾向于在数据和索引之间进行显式配对。它并不难,而且不再更长。
Oracle应该向Postgres学习,unnest(array) with ordinality
可以解决这种情况,这显然是可以理解的,值得信赖的且具有文档证明的功能。