虽然我认为 Erwin 的解决方案可能更可取,如果您可以重新构造表,则不需要任何架构更改的替代方法是编写一个 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);
在这种情况下,它们在创建后完全没有联系。