Решение за простия случай
Както е обяснено в посочените отговори по-долу, можете да използвате регистрирани типове (редове) и по този начин имплицитно да декларирате връщания тип на полиморфна функция:
CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;
Обадете се:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Връща пълната таблица (с всички потребителски колони).
Чакай! Как?
Подробно обяснение в този свързан отговор, глава„Различни типове пълни таблици“ :
- Рефакторирайте функция PL/pgSQL, за да върнете резултатите от различни SELECT заявки
TABLE foo
е просто съкращение от SELECT * FROM foo
:
- Има ли пряк път за SELECT * FROM?
2 стъпки за напълно динамичен тип връщане
Но това, което се опитвате да направите, е абсолютно невъзможно в единично SQL команда.
Искам да предам
schema_name
иtable_name
като параметри за функциониране и получаване на списък със записи, споредcolumn_visible
поле вpublic.fields
маса.
Няма директен начин за връщане на произволен избор на колони (тип на връщане, неизвестен по време на извикване) от функция - или който и да е SQL команда. SQL изисква да знае номера, имена и типове на получените колони по време на повикване. Повече във 2-ра глава на този свързан отговор:
- Как да генерирам завъртано CROSS JOIN, където получената дефиниция на таблицата е неизвестна?
Има различнизаобиколни решения . Можете да увиете резултата в един от стандартните типове документи (json
, jsonb
, hstore
, xml
).
Или генерирате заявката с едно извикване на функция и изпълнявате резултата със следното:
CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
RETURNS text AS
$func$
SELECT format('SELECT %s FROM %I.%I'
, string_agg(quote_ident(column_name), ', ')
, schema_name
, table_name)
FROM fields
WHERE column_visible
AND schema_name = _schema_name
AND table_name = _table_name
GROUP BY schema_name, table_name
ORDER BY schema_name, table_name;
$func$ LANGUAGE sql;
Обадете се:
SELECT public.generate_get_table('public', 'users');
Това създава заявка от формата:
SELECT usr_id, usr FROM public.users;
Изпълнете го във 2-ра стъпка. (Може да искате да добавите номера на колони и колони за поръчка.)
Или добавете \gexec
в psql, за да изпълни незабавно върнатата стойност. Вижте:
Как да принудим оценка на подзаявката преди присъединяване/натискане надолу към чужд сървър
Защитете се срещу SQL инжектиране:
- INSERT с динамично име на таблица в тригерна функция
- Да дефинирате имената на таблици и колони като аргументи във функция plpgsql?
varchar(100)
няма много смисъл за идентификатори, които са ограничени до 63 знака в стандартния Postgres:
- Максимален брой знаци в етикетите (имена на таблици, колони и т.н.)
Ако разбирате как идентификаторът на обекта тип regclass
работи, можете да замените схемата и името на таблицата с един единствен regclass
колона.