SELECT * FROM TABLE(流水线函数):我可以确定结果中行的顺序吗?
Posted
技术标签:
【中文标题】SELECT * FROM TABLE(流水线函数):我可以确定结果中行的顺序吗?【英文标题】:SELECT * FROM TABLE(pipelined function): can I be sure of the order of the rows in the result? 【发布时间】:2013-05-23 11:41:17 【问题描述】:在下面的例子中,我总是会得到“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());
谢谢。
【问题讨论】:
:是的,如果你颠倒了 PIPE ROW 的顺序,那么它会给你输出 2,1 否则 1,2 。如果你想要特定的顺序,然后在中添加一个 order by 子句您的选择查询。否则选择查询将根据 PIPE ROW 序列返回数据 【参考方案1】:我认为文档中没有任何地方可以保证返回数据的顺序。
有一个 2003 年的旧 Tom Kyte thread(所以 可能 已经过时了)声明不建议依赖隐式顺序,原因与您不依赖在普通 SQL 中排序。
1st:是从表函数返回的行的顺序 SQL 语句与“管道”条目的顺序完全相同 进入内部集合(因此不需要 order by 子句)?
...
跟进 2003 年 5 月 18 日 - 世界标准时间上午 10 点:
1) 也许,也许不是,我不会指望它。你不应该数 在结果集中的行顺序上,没有 order by。如果 你加入或做一些更复杂的事情,然后简单地“选择 * from 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.
【讨论】:
感谢您的回答,Tom Kyte 2003 年的回答非常有趣。【参考方案2】:此过程逻辑的工作方式与基于表的查询不同。您不能依赖从表中选择的顺序的原因是,您不能依赖 RDBMS 将行标识为所需集合的一部分的顺序。这部分是因为执行计划发生了变化,部分是因为很少有情况可以预测表中行的物理顺序。
但是,您在这里选择的函数可以保证从函数发出行的顺序。在没有连接、聚合或其他任何东西的情况下(即直接“从表(函数)中选择...”),我可以肯定行顺序是确定性的。
除非有明确的 order-by,否则该建议不适用于涉及表的地方,因此,如果您从不使用 order-by 的查询中加载 pl/sql 集合,那么当然行的顺序在集合中是不确定的。
【讨论】:
【参考方案3】:此时已接受答案中的 AskTom 链接已损坏,但我找到了 newer yet very similar question。在一些“对乒乓球的误解”之后,Connor McDonald 最终承认,在涉及并行性和引用光标的某些条件下,排序是稳定的,并且仅与当前版本相关。引用:
并行性是这里的(潜在)风险。 正如当前所代表的,一个流水线函数只有在将引用光标作为输入时才能并行运行。当然,不能保证将来不会改变。 因此,您可以基于 假设 运行,即在 当前 版本中,您将按顺序恢复行,但您永远不能 100% 相信现在和永远都是这种情况.
因此不保证未来的版本。
有问题的函数会通过这个标准,因此它应该提供稳定的排序。但是,我个人不会相信它。我的情况(当我发现这个问题时)更简单:从字面上指定的集合中选择 - select column_value from table(my_collection(5,3,7,2))
无论如何我更喜欢数据和索引之间的显式配对。这不是那么难,也不会更长。
Oracle 应该向 Postgres 学习,unnest(array) with ordinality
解决了这种情况,这是一个清晰易懂、值得信赖且有据可查的特性。
【讨论】:
以上是关于SELECT * FROM TABLE(流水线函数):我可以确定结果中行的顺序吗?的主要内容,如果未能解决你的问题,请参考以下文章
Mysql DB select from table where field语句java
select * from table where something VS select column from table where something
SqlServer对select * from (select *from table) 支持
select into from 与insert into select from区别
Mysql select id from table1 and select count(id) from table2