SELECT * FROM TABLE(流水线函数):我可以确定结果中行的顺序吗?

时间:2013-05-23 11:41:17

标签: oracle plsql pipelined-function

在下面的示例中,我是否总是得到“1,2”,或者是否可以获得“2,1”并且您能告诉我您在文档中的哪个位置可以保证它是否存在?

如果答案是肯定的,则意味着没有ORDER BYORDER 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());

谢谢。

3 个答案:

答案 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可以解决这种情况,这显然是可以理解的,值得信赖的且具有文档证明的功能。