2016-12-29 6 views
1

Я создал пользовательскую функцию в pl/pgsql, и это только входной массив. Я хотел бы использовать результат запроса как вход для этой настраиваемой функции, но не может показаться, что это правильно. Я буду использовать более простую функцию в качестве примера, а также более простой запрос, чем тот, который я пытаюсь использовать в качестве ввода.Использовать SQL-запрос как параметр массива (ввод) в пользовательской функции

Определение функции:

CREATE OR REPLACE FUNCTION bigger_than_ones(input_array int[]) 
returns SETOF int 
AS 
$$ 
DECLARE 
    array_item int; 
BEGIN 
    FOREACH array_item in ARRAY input_array 
    LOOP 
    IF array_item > 1 THEN 
     RETURN NEXT array_item; 
    END IF; 
    END LOOP; 
END 
$$ LANGUAGE plpgsql; 

У меня есть таблица, которая имеет столбец такой же тип данных и тип данных массива. В этом случае числа колонок:

SELECT * FROM my_table; 
id | int_attribute 
---+-------------- 
1 | 2 
2 | 3 
3 | 1 
4 | 4 
5 | 1 
6 | 6 
7 | 1 
8 | 1 
9 | 8 

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

SELECT * FROM bigger_than_ones(SELECT int_attribute FROM my_table); 

Для возврата:

result 
------------- 
2 
3 
4 
6 
8 

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

Любые мысли о том, что мне не хватает?

+1

Мне непонятно, чего вы пытаетесь достичь с помощью запроса. Пожалуйста, отредактируйте свой вопрос и добавьте примерные данные и ожидаемый результат на основе этих данных. [_Formatted_] (http://stackoverflow.com/help/formatting) ** текст **, пожалуйста, [без скриншотов] (http://meta.stackoverflow.com/questions/285551/why-may-i-not -upload-images-of-code-on-so-when-ask-a-question/285557 # 285557) –

+0

это не просто 'select int_attribute from my_table, где int_attribute> 1'? –

+0

ваша функция ожидает ** массив **. Почему вы думаете, что можете (или должны) передать ему простое целочисленное значение? Почему вы так определили свою функцию? –

ответ

1

Что вы нашли: ARRAY constructor, что не Оператор (или функция), а SQL-конструктор (элемент синтаксиса SQL). В ответном ответе использовался неверный термин (теперь он исправлен). Разница может иметь значение.

SELECT * FROM bigger_than_ones(ARRAY(SELECT int_attribute FROM my_table)); 

Вы также можете использовать основной aggregate function array_agg(), который легче интегрировать в более сложные запросы - но медленнее, для простого случая:

SELECT * FROM bigger_than_ones((SELECT array_agg(int_attribute) FROM my_table)); 

Связанный:

Я предполагаю, что вы aw unnest()? Он может быть использован радикально упростить тестовую функцию:

CREATE OR REPLACE FUNCTION bigger_than_ones(input_array int[]) 
    RETURNS SETOF int AS 
$func$ 
    SELECT * 
    FROM unnest(input_array) elem 
    WHERE elem > 1; 
$func$ LANGUAGE sql; 

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

+0

Я не знал о 'unnest()' выглядит очень полезно, спасибо. Причина, по которой я использую аналогично структурированную функцию, заключается в том, что мне нужно рассчитать полученные объединенные диапазоны времени (настраиваемый тип) из нескольких таблиц, в нескольких местах в моем коде. Моя лучшая мысль заключалась в том, чтобы создать функцию, которая будет делать это, используя в качестве входных данных все временные диапазоны, независимо от того, откуда я ее взял, поэтому мне не пришлось бы делать более сложный запрос каждый раз. Извините, если что-то недостаточно ясно, английский не является моим первым языком. – shevia

+0

@shevia: После вашего обновления вопрос достаточно ясен. Яснее большинства, на самом деле. Одно большое упущение: ваша версия Postgres - должна быть объявлена ​​в * каждом * вопросе. Просто хотел бы упомянуть о том, что * может быть лучшим подходом. Возможно, нет. Может быть, пользовательская функция агрегата? Или 'tstzrange (min (lower (...), max (upper (...))'. Вы можете задать другой вопрос с точными * точками ваших настроек и требований. –

-2

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

Вот пример:

создать или заменить ТИП NameArray КАК VARRAY (3) VARCHAR2 (10);

+1

Это недопустимо для Postgres –

0

я наконец-то нашел решение в другой SO вопрос: Store select query's output in one array in postgres

я был в состоянии использовать оператор массива() следующим образом:

SELECT * FROM bigger_than_ones(ARRAY(SELECT int_attribute FROM my_table)); 

И получил ожидаемый результат.

 Смежные вопросы

  • Нет связанных вопросов^_^