テーブルを再構築できる場合、Erwin のソリューションがおそらく望ましいと思いますが、スキーマの変更を必要としない代替手段は、システム カタログ情報に基づいて動的 SQL を使用してテーブルをスキャンする PL/PgSQL 関数を作成することです。
与えられた:
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 が返されます。複数の一致がある場合、結果はそれらの 1 つになりますが、どれが一致するかは保証されません。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);
その場合、それらは作成後に互いに完全に接続されていません。