И в двата случая имате нужда от динамичен SQL.
Име на таблица като зададен параметър
CREATE OR REPLACE FUNCTION foo(_number int)
RETURNS TABLE (cpa int, nr text, vym text) AS -- adapt to actual data types!
$func$
BEGIN
RETURN QUERY EXECUTE format(
'SELECT t.cpa, substring(t.ku,'[0-9]+'), p.vym
FROM public."table_data_C" t
LEFT JOIN %s p USING (cpa)'
, 'pa' || _number
);
END
$func$ LANGUAGE plpgsql;
Обаждане:
SELECT * FROM foo(456887)
По принцип бихте дезинфекцирали имената на таблици с format ( %I )
за да избегнете SQL инжектиране. Само с integer
като динамичен вход, който не е необходим. Повече подробности и връзки в този свързан отговор:
INSERT с име на динамична таблица във функция за задействане
Модел на данни
Може да има основателни причини за модела на данни. Като разделяне/шардинг или отделни привилегии...
Ако нямате толкова основателна причина, помислете за консолидиране на няколко таблици с идентична схема в една и добавете number
като колона. Тогава нямате нужда от динамичен SQL.
Помислете за наследяване
. След това можете да добавите условие към tableoid
за извличане само на редове от дадена дъщерна таблица:
SELECT * FROM parent_table
WHERE tableoid = 'pa456887'::regclass
Все пак имайте предвид ограниченията за наследяването. Свързани отговори:
- Получаване на името на изходната таблица на ред при заявка към родителя, от който наследява
- Изберете (извлечете) всички записи от множество схеми с помощта на Postgres
Име на 2-ра таблица в зависимост от стойността в 1-ва таблица
Извличането на името на таблицата за свързване от стойностите в първата таблица динамично усложнява нещата.
Само за няколко маси
LEFT JOIN
всеки на tableoid
. Има само едно съвпадение на ред, така че използвайте COALESCE
.
SELECT t.*, t.tbl, COALESCE(p1.vym, p2.vym, p3.vym) AS vym
FROM (
SELECT cpa, ('pa' || substring(ku,'[0-9]+'))::regclass AS tbl
FROM public."table_data_C"
-- WHERE <some condition>
) t
LEFT JOIN pa456887 p1 ON p1.cpa = t.cpa AND p1.tableoid = t.tbl
LEFT JOIN pa456888 p2 ON p2.cpa = t.cpa AND p2.tableoid = t.tbl
LEFT JOIN pa456889 p3 ON p3.cpa = t.cpa AND p3.tableoid = t.tbl
За много таблици
Комбинирайте цикъл с динамични заявки:
CREATE OR REPLACE FUNCTION foo(_number int)
RETURNS TABLE (cpa int, nr text, vym text) AS
$func$
DECLARE
_nr text;
BEGIN
FOR _nr IN
SELECT DISTINCT substring(ku,'[0-9]+')
FROM public."table_data_C"
LOOP
RETURN QUERY EXECUTE format(
'SELECT t.cpa, _nr, p.vym
FROM public."table_data_C" t
LEFT JOIN %I p USING (cpa)
WHERE t.ku LIKE (_nr || '%')'
, 'pa' || _nr
);
END LOOP;
END
$func$ LANGUAGE plpgsql;