Выполнить SELECT с динамическим выражением ORDER BY внутри функции - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь ВЫПОЛНИТЬ некоторые SELECT для использования внутри функции, мой код выглядит примерно так:

DECLARE
result_one record;

BEGIN 
    EXECUTE 'WITH Q1 AS 
        (
            SELECT id
            FROM table_two
            INNER JOINs, WHERE, etc, ORDER BY... DESC
        )

        SELECT Q1.id
        FROM Q1 
        WHERE, ORDER BY...DESC';

RETURN final_result;
END;    

Я знаю, как это сделать в MySQL, но в PostgreSQL у меня не получается. Что я должен изменить или как я должен это сделать?

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Что сказал a_horse. И:

Плюс , чтобы динамически выбрать столбец для ORDER BY, вы должны добавить этот столбец в список SELECT вашего CTE, что приводит к осложнениям, если столбец может быть продублирован (как при передаче'id') ...

Еще лучше, полностью удалить CTE .В любом случае, в вашем вопросе нет ничего, что могло бы гарантировать его использование.(Используйте CTE только тогда, когда необходимо в Postgres, они обычно медленнее, чем эквивалентные подзапросы или простые запросы.)

CREATE OR REPLACE FUNCTION get_data(p_sort_column text)
  RETURNS TABLE (id integer) AS
$func$
BEGIN
RETURN QUERY EXECUTE format(
   $q$ 
   SELECT t2.id  -- assuming you meant t2?
   FROM   table_two   t2
   JOIN   table_three t3 on ...
   ORDER  BY t2.%I DESC NULL LAST  -- see below!
   $q$, $1);
END
$func$  LANGUAGE plpgsql;

Я добавил NULLS LAST - вы, вероятно, тоже этого захотите:

Если p_sort_column все время находится в одной и той же таблице, жесткий кодэто имя таблицы / псевдоним в предложении ORDER BY.Иначе, передайте имя таблицы / псевдоним отдельно и автоматически заключите их в кавычки для безопасности:

Предлагаю квалифицировать в таблице все имена столбцов в большем запросе с несколькими объединениями (t2.id, а не только id).Предотвращает различные неожиданные результаты / путаницу / злоупотребления.

И вы можете захотеть квалифицировать схемы именами таблиц (myschema.table_two), чтобы избежать подобных проблем при вызове функции с другим search_path:

0 голосов
/ 12 ноября 2018

Чтобы функция могла возвращать несколько строк, она должна быть объявлена ​​как returns table() (или returns setof)

И для фактического возврата результата из функции PL / pgSQL вам необходимоиспользовать return query (как описано в руководстве )

Для построения динамического SQL в Postgres настоятельно рекомендуется использовать функцию format() для правильной работы с идентификаторами (и дляисточник легче читается)LIMIT или distinct on () внутри запроса.


Вы можете сделать свою жизнь еще проще, если для динамического SQL используйте другой уровень цитирования в долларах:

create or replace function get_data(p_sort_column text)
  returns table (id integer)
as
$$
begin
  return query execute 
    format(
     $query$ 
       with q1 as (
           select id
           from table_two
             join table_three on ...
         )
         select q1.id
         from q1
         order by %I desc
     $query$, p_sort_column);
end;
$$
language plpgsql;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...