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 Это четко понятная, заслуживающая доверия и хорошо задокументированная функция.

Другие вопросы по тегам