1

Это следующий вопрос к earlier one. У меня есть хранимая функция f1, которая принимает два аргумента, возвращает таблицу с 5 столбцами; теперь возвращаемые значения являются постоянными, позже они будут вычисляться из аргументов.«ОШИБКА: столбец ... указанный более одного раза» в определении VIEW

У меня также есть таблица t1 с двумя столбцами, которые соответствуют по типу аргументам f1.

Теперь я хотел бы определить вид v1, который содержит объединение всех строк, возвращаемых с f1 для всех пар аргументов, хранящихся в t1. Для приведенного примера значения результат должен быть:

+---+---+---+---+---+---+---+ 
| 2 | 3 | a | b | 1 | c | d | 
+---+---+---+---+---+---+---+ 
| 4 | 5 | a | b | 1 | c | d | 
+---+---+---+---+---+---+---+ 

Если первые два столбца лишены, что было бы хорошо, как хорошо. Обратите внимание, что f1 может возвращать несколько строк для определенных значений аргументов.

Я попробовал следующее заявление, но это дает мне сообщение об ошибке:

ERROR: column "c4" specified more than once 
CREATE VIEW v1 (c1, c2, c3, c4, c5) 
AS SELECT * FROM 
    (SELECT c1, c2 FROM t1) AS x, 
    f1 (x.c1, x.c2); 

Что я делаю неправильно?

Вот предшествующие заявления, чтобы установить пример вверх:

CREATE OR REPLACE FUNCTION f1 (a1 INTEGER, a2 INTEGER) 
RETURNS TABLE (c1 VARCHAR(20), c2 VARCHAR(20), c3 INTEGER, c4 VARCHAR(20), c5 VARCHAR(128)) 
AS $$ 
SELECT 'a'::VARCHAR(20), 'b'::VARCHAR(20), 1::INTEGER, 'c'::VARCHAR(20), 'd'::VARCHAR(128); 
$$ LANGUAGE SQL; 

DROP TABLE IF EXISTS t1; 
CREATE TABLE t1 (c1 INTEGER, c2 INTEGER); 
INSERT INTO t1 (c1, c2) 
VALUES (2,3), (4,5); 

DROP VIEW IF EXISTS v1; 
+1

Не используйте '' * выберите - вместо того, чтобы выбрать поля, которые нужно. Как есть, 'c1' существует как в' f1', так и 't1' ... – sgeddes

+0

@sgeddes Я попробую, но сообщение об ошибке цитирует' c4'. Отличные ответы PostgreSQL здесь, BTW. – Drux

ответ

1

Я предлагаю LATERAL присоединиться к SELECT запроса:

CREATE VIEW v1 AS 
SELECT f.* 
FROM t1 
    , f1 (t1.c1, t1.c2) AS f; -- implicit CROSS JOIN LATERAL 

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

Создание представления работает с ранним связыванием в любом случае. Смысл, только столбцы, выбранные во время создания, включены в представление. Если позднее вы измените определение функции, чтобы вернуть дополнительный столбец, то это не, включенное в представление. (Если удалить или переименовать столбцы, вы нарушаете вид.)

Вы могли также включать функцию f1(..) в SELECT списке, чтобы почти тот же эффект возвращения установка. Отличия:

  • Set-функции, возвращающие в SELECT списке нарушают стандарт SQL и неодобрением некоторыми. Также не переносится на некоторые другие РСУБД. Поскольку Postgres представил (стандартный SQL) LATERAL с Postgres 9.3, это обычно предпочтительнее.

  • А-функция множества возвращения в SELECT списка (эффективно коррелированных подзапросов) является эквивалентом LEFT JOIN LATERAL ... ON true, т.е. он сохраняет все строки t1, даже если функция не возвращает ни одной строки. CROSS JOIN LATERAL, как указано выше удаляет строк, где f1() не возвращает строки.

  • Вы можете разложить четко определенный тип строки, возвращаемой из функции с SELECT (f1(...)).*, ..., но функция может быть оценена повторно для каждого столбца в тип возвращаемого вместо только один раз.

Похожие и более подробную информацию:

+0

Отлично. (Переучивание PostgreSQL в спешке ... ;-) – Drux