Как использовать функцию для получения имени таблицы в postgresql?

Спасибо за помощь. Извините за плохой английский.

Я создал функцию для возврата имени таблицы для использования в моем операторе выбора, здесь скрипт функции:

CREATE OR REPLACE FUNCTION getfromtable(objecttype varchar, destinationtable varchar, firstdate date, OUT tablename varchar)
AS $BODY$
declare 
 objectType       ALIAS FOR $1;
 destinationTable ALIAS FOR $2;
 firstDate        ALIAS FOR $3;
 --tableResult varchar;
BEGIN
   IF UPPER(objectType) = 'VIEW' THEN
      select destinationTable || to_char(cast(firstDate as date),'yy') into tablename;
   END IF;
   IF UPPER(objectType) = 'TABLE' THEN
      select destinationTable || to_char(cast(firstDate as date),'mmyy') into tablename;
   END IF;
END;
$BODY$
LANGUAGE plpgsql

Мне нужно использовать эту функцию, потому что у меня есть имена таблиц с MMYY или представления с YY в имени... функция работает правильно, но мне нужно использовать ее при выборе, например:

select * from getfromtable('TABLE','tab_venda_',current_date)

Но вот моя проблема: если я выполняю скрипт, postgres возвращает имя таблицы, но не выполняет выбор из таблицы... мне нужно выполнить выбор в таблице, а не возвращать функцию...

Как бы я хотел, чтобы это было

select * from tab_venda_0319

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


person Nycolas Merino    schedule 13.03.2019    source источник
comment
Как вы хотите выполнять эти запросы? Внутри тела функции PL/pgSQL? Или использовать какой-то язык, который подключается к базе данных и может использовать динамический SQL? Потому что для этого вам нужен динамический SQL, а простой SQL их не поддерживает.   -  person Łukasz Kamiński    schedule 13.03.2019
comment
@ ŁukaszKamiński я хочу выполнить его в PL/pgSQL ... Ниже приведены некоторые примеры имен таблиц: tab_venda0319, tab_venda0219, tab_venda0119 movprodd19, movprodd18, vdadet0119, vdadet0219 .. Я хочу выполнить функцию или любое другое решение, чтобы получить имя таблицы, используя таблица префиксов: выберите * из getfromtable ('TABLE', 'tab_venda_', current_date), если я хочу: выберите * форму tab_venda_0319   -  person Nycolas Merino    schedule 13.03.2019
comment
У меня слишком мало времени, чтобы сделать что-то, что могло бы квалифицировать IMO как ответ, но в документации есть отличный раздел о динамическом SQL, включая простые для понимания примеры: postgresql.org/docs/current/   -  person Łukasz Kamiński    schedule 13.03.2019
comment
Не имеет отношения, но: objectType ALIAS FOR $1; бесполезен, так как ваш первый параметр уже называется objectType   -  person a_horse_with_no_name    schedule 13.03.2019


Ответы (2)


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

Возможно, вам поможет разделение?

person Uwe Ohse    schedule 13.03.2019
comment
Извините за плохой английский, спасибо за ответ! Разделение мне не помогает... Имена таблиц создаются системой, и система работает в производственной среде. Моя функция получает правильное имя таблицы, но не делает выбор * из :( - person Nycolas Merino; 13.03.2019

Вместо возврата имени таблицы вы можете вернуть результат запроса. См. модифицированную функцию.

CREATE OR REPLACE FUNCTION getfromtable(objecttype varchar, destinationtable varchar, firstdate date) 
RETURNS SETOF RECORD
AS $BODY$
declare 
 objectType       ALIAS FOR $1;
 destinationTable ALIAS FOR $2;
 firstDate        ALIAS FOR $3;
 tablename varchar;
BEGIN
   IF UPPER(objectType) = 'VIEW' THEN
      select destinationTable || to_char(cast(firstDate as date),'yy') into tablename;
   END IF;
   IF UPPER(objectType) = 'TABLE' THEN
      select destinationTable || to_char(cast(firstDate as date),'mmyy') into tablename;
   END IF;
   RETURN QUERY EXECUTE 'SELECT * FROM '||tablename;
END;
$BODY$
LANGUAGE plpgsql;

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

SELECT * FROM getfromtable('TABLE','tab_venda_',current_date) AS tab(column1_name column1_type, ...);
person vmaroli    schedule 13.03.2019
comment
Мне нужно передать имя и тип всех столбцов в инструкции SELECT * FROM getfromtable('TABLE','tab_venda_',current_date) AS t(col1_name col1_type, ...); ? - person Nycolas Merino; 13.03.2019
comment
да, вам нужно указать все столбцы и их тип. - person vmaroli; 13.03.2019
comment
Это тяжело, это ERP-система и в какой-то таблице по 30-50 столбцов, и система постоянно находится в процессе атуализации. - person Nycolas Merino; 13.03.2019
comment
@NycolasMerino Если вы планируете использовать эти данные в функции PL/pgSQL, то я думаю, что было бы лучше просто вернуть имя таблицы и запрос EXECUTE в функции, которая что-то делает с данными. Это не потребует перечисления столбцов и их типов. Я думаю, что у SRF все еще может быть проблема с производительностью, которая требует, чтобы функция получила полный результат, прежде чем она начнет его возвращать, что может использовать некоторую память или дисковое пространство и вызвать проблемы, если таблица достаточно велика. - person Łukasz Kamiński; 13.03.2019
comment
@ ŁukaszKamiński Спасибо за ответ, извините за плохой английский. Я не могу просто указать имя таблицы и выполнить, потому что скрипт выполнялся еженедельно, когда месяц меняется, мне нужно редактировать имя таблицы для нового месяца. Запрос выполняется в PL/pgSQL, однако он автоматически отображается на панели инструментов. - person Nycolas Merino; 13.03.2019