Понимание Set Returning Function (SRF) в списке SELECT

8

Почему существует различие в поведении между использованием функции возврата набора (SRF) в списке SELECT и использованием SRF в предложении FROM?

Например, для простого SRF, возвращающего 2 строки:

CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
  RETURNS SETOF record AS $$
  SELECT 1,1
  UNION
  SELECT 2,2;
$$ LANGUAGE SQL;

SELECT gen_series(); возвращает две строки одного столбца, каждая из которых содержит запись:

=>  gen_series 
------------
 (1,1)
 (2,2)
(2 rows)

Принимая во внимание, что SELECT * FROM gen_series();возвращает две строки с расширенной записью:

=>  column1 | column2 
---------+---------
       1 |       1
       2 |       2
(2 rows)

Для сравнения: если SRF возвращает один столбец, то вызов SRF в предложении SELECT или FROM не имеет значения. например:

=> SELECT generate_series(1,2);
 generate_series 
-----------------
               1
               2
(2 rows)

=> SELECT * FROM generate_series(1,2);
 generate_series 
-----------------
               1
               2
(2 rows)

Мои вопросы:

  1. Я не совсем понимаю, почему во втором случае поведение SRF отличается от первого случая только потому, что возвращаемая таблица имеет один столбец. Это действительно последовательное поведение с точки зрения типов, кортежей и множеств?

  2. Какая разница между двумя случаями, которая приводит к разному поведению?

  3. SRF можно использовать в качестве таблиц, как показано выше, но можно ли использовать таблицы для замены SRF? например

    SELECT my_table; 

По-видимому, этого нельзя сделать, но почему это SELECT my_SRF();возможно, а SELECT my_table;не разрешено (с точки зрения отношений и математики)?

tinlyx
источник
SELECT my_table;недопустимый синтаксис
Младен Узелац

Ответы:

3

Postgres относится к простому случаю по-другому. Несколько столбцов обрабатываются как составной тип (строка таблицы), который разделяется только на один SELECT * FROM ..., в то время как один столбец скалярного типа обрабатывается только как это, без добавления оболочки составного типа. Так что SELECT my_SRF()выдает так же, как и SELECT * FROM my_SRF()для простого случая. Руководство по табличным функциям :

Табличные функции - это функции, которые создают набор строк, состоящий из базовых типов данных (скалярных типов) или составных типов данных (строк таблицы).

Я согласен, что это сбивает с толку, и вы не первый, кто запутался. (Однако рассмотрим альтернативный вариант: добавление обертки составного типа вокруг одного столбца может быть еще более запутанным.)

Но не так запутанно, как то, что происходит, когда вы комбинируете несколько функций SRF в SELECTсписке. Это изменится с Postgres 10 навсегда, хотя:

Безопасный, менее запутанный способ для любого случая - переместить функции SRF в FROMпредложение. Используйте LATERALобъединение, если вам нужно сослаться на столбцы из другой таблицы. Руководство предлагает:

LATERALСинтаксис производит менее удивительные результаты при вызове нескольких возвращающих набор функций, и обычно должны использоваться вместо этого.

Эрвин Брандштеттер
источник