SELECT * FROM TABLE(конвейерная функция): могу ли я быть уверен в порядке строк в результате?
В следующем примере я всегда получу "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());
Спасибо.
2 ответа
Я не думаю, что в документации есть место, которое гарантирует порядок возврата данных.
Существует старая ветка Tom Kyte 2003 года (которая может быть устаревшей), в которой говорится, что полагаться на неявный порядок не рекомендуется, по тем же причинам, по которым вы не будете полагаться на порядок в обычном SQL.
1-й: является ли порядок строк, возвращаемых табличной функцией в операторе SQL, точно таким же порядком, в котором записи были "переданы" во внутреннюю коллекцию (так что нет необходимости в выражении order by)?
...
Продолжение 18 мая 2003 г. - 10:00 UTC:
1) может, а может и нет, я бы на это не рассчитывал. Вы не должны рассчитывать на порядок строк в наборе результатов, не имея порядка по. Если вы присоединитесь или сделаете что-то более сложное, чем просто "выберите * из таблицы ( f(x))", строки вполне могут вернуться в каком-то другом порядке.
эмпирически - они, кажется, возвращаются, как они по трубопроводу. Я не верю, что задокументировано, что это так.
Фактически, коллекции типа NESTED TABLE документированы так, чтобы явно не иметь возможности сохранять порядок.
Чтобы быть в безопасности, вы должны делать, как всегда, в запросе, указывать явный ORDER BY, если вы хотите упорядочить результаты запроса.
Сказав, что я взял вашу функцию и выполнил 10 миллионов итераций, чтобы проверить, был ли когда-нибудь нарушен неявный порядок; это не было
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.
Эта процедурная логика работает иначе, чем запросы на основе таблиц. Причина, по которой вы не можете полагаться на заказы в выборе из таблицы, заключается в том, что вы не можете полагаться на порядок, в котором СУБД будет определять строки как часть необходимого набора. Отчасти это связано с изменением планов выполнения, а отчасти потому, что существует очень мало ситуаций, в которых физический порядок строк в таблице является предсказуемым.
Однако здесь вы выбираете функцию, которая гарантирует порядок, в котором строки выводятся из функции. В отсутствие объединений, агрегаций или чего-либо еще (т. Е. Для прямого "выбора... из таблицы (функции)") я был бы совершенно уверен, что порядок строк является детерминированным.
Этот совет неприменим, если в нем задействована таблица, если нет явного упорядочения, поэтому, если вы загружаете свою коллекцию pl/sql из запроса, который не использует упорядоченный порядок, то, конечно, порядок строк в коллекции не является детерминированным.
Ссылка AskTom в принятом ответе сейчас не работает, но я нашел более новый, но очень похожий вопрос. После некоторого "непонимания пинг-понга" Коннор Макдональд наконец признает, что упорядочение стабильно при определенных условиях, включая параллелизм и рефкурсоры, и относится только к текущим выпускам. Цитата:
Параллелизм здесь является (потенциальным) риском. В настоящее время конвейерная функция может выполняться параллельно, только если она принимает на вход указатель ref. Конечно, нет никаких гарантий, что это не изменится в будущем. Таким образом, вы можете исходить из предположения, что в текущих выпусках вы вернете строки в порядок, но вы никогда не сможете на 100% полагаться на то, что так будет сейчас и всегда.
Так что никаких гарантий для будущих выпусков не дается.
Рассматриваемая функция будет соответствовать этому критерию, следовательно, она должна обеспечивать стабильный порядок. Однако лично я бы этому не поверил. Мой случай (когда я нашел этот вопрос) был еще проще: выбор из коллекции, указанной буквально -
select column_value from table(my_collection(5,3,7,2))
и в любом случае я предпочел явное объединение данных и индекса. Это не так сложно и ненамного дольше.
Oracle должен узнать у Postgres, где эта ситуация решается с помощью
unnest(array) with ordinality
Это четко понятная, заслуживающая доверия и хорошо задокументированная функция.