Хотя я думаю, что решение Эрвина, вероятно, предпочтительнее, если вы можете реструктурировать свои таблицы, альтернативой, которая не требует каких-либо изменений схемы, является написание функции PL/PgSQL, которая сканирует таблицы с использованием динамического SQL на основе информации из системного каталога.
Дано:
CREATE SCHEMA a;
CREATE SCHEMA b;
CREATE TABLE a.testtab ( searchval text );
CREATE TABLE b.testtab (LIKE a.testtab);
INSERT INTO a.testtab(searchval) VALUES ('ham');
INSERT INTO b.testtab(searchval) VALUES ('eggs');
Следующая функция PL/PgSQL ищет во всех схемах, содержащих таблицы с именем _tabname
, значения в _colname
, равные _value
, и возвращает первую подходящую схему.
CREATE OR REPLACE FUNCTION find_schema_for_value(_tabname text, _colname text, _value text) RETURNS text AS $$
DECLARE
cur_schema text;
foundval integer;
BEGIN
FOR cur_schema IN
SELECT nspname
FROM pg_class c
INNER JOIN pg_namespace n ON (c.relnamespace = n.oid)
WHERE c.relname = _tabname AND c.relkind = 'r'
LOOP
EXECUTE
format('SELECT 1 FROM %I.%I WHERE %I = $1',
cur_schema, _tabname, _colname
) INTO foundval USING _value;
IF foundval = 1 THEN
RETURN cur_schema;
END IF;
END LOOP;
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
Если совпадений нет, возвращается null. Если есть несколько совпадений, результатом будет одно из них, но нет никаких гарантий относительно того, какое именно. Добавьте предложение ORDER BY
в запрос схемы, если вы хотите вернуть (скажем) первое в алфавитном порядке или что-то в этом роде. Функция также тривиально изменена, чтобы возвращать setof text
и RETURN NEXT cur_schema
, если вы хотите вернуть все совпадения.
regress=# SELECT find_schema_for_value('testtab','searchval','ham');
find_schema_for_value
-----------------------
a
(1 row)
regress=# SELECT find_schema_for_value('testtab','searchval','eggs');
find_schema_for_value
-----------------------
b
(1 row)
regress=# SELECT find_schema_for_value('testtab','searchval','bones');
find_schema_for_value
-----------------------
(1 row)
Кстати, вы можете повторно использовать определения таблиц без наследования, если хотите, и вы действительно должны. Либо используйте общий составной тип данных:
CREATE TYPE public.testtab AS ( searchval text );
CREATE TABLE a.testtab OF public.testtab;
CREATE TABLE b.testtab OF public.testtab;
в этом случае они используют один и тот же тип данных, но не какие-либо данные; или или через LIKE
:
CREATE TABLE public.testtab ( searchval text );
CREATE TABLE a.testtab (LIKE public.testtab);
CREATE TABLE b.testtab (LIKE public.testtab);
в этом случае они полностью не связаны друг с другом после создания.
person
Craig Ringer
schedule
16.10.2012