Sql 找出基于表值的模式
我的数据库根据客户机划分为模式(即:每个客户机都有自己的模式,具有相同的数据结构) 我还碰巧有一个外部操作,它不知道应该以哪个模式为目标。它来自系统的另一个部分,它没有客户机的概念,也不知道它在哪个客户机集中运行。在处理它之前,我必须找出该请求需要以哪个模式为目标 为了找到正确的模式,我必须找出哪个保存了具有特定唯一ID(字符串)的记录Sql 找出基于表值的模式,sql,django,postgresql,database-connection,postgresql-9.2,Sql,Django,Postgresql,Database Connection,Postgresql 9.2,我的数据库根据客户机划分为模式(即:每个客户机都有自己的模式,具有相同的数据结构) 我还碰巧有一个外部操作,它不知道应该以哪个模式为目标。它来自系统的另一个部分,它没有客户机的概念,也不知道它在哪个客户机集中运行。在处理它之前,我必须找出该请求需要以哪个模式为目标 为了找到正确的模式,我必须找出哪个保存了具有特定唯一ID(字符串)的记录R 根据我的理解,以下是 SET search_path TO schema1,schema2,schema3,... 将只查看schema1中的表(或与该表匹
R
根据我的理解,以下是
SET search_path TO schema1,schema2,schema3,...
将只查看schema1中的表(或与该表匹配的第一个架构),而不会进行全局搜索
有没有一种方法可以让我在所有模式中进行全局搜索,或者我只需要使用for循环并一次遍历所有模式?您必须遍历所有名称空间。您可以从
pg.*
系统目录中获得大量此类信息。理论上,您应该能够在请求时解析client->schema映射,而无需与数据库通信,因此您进行的第一个SQL调用是:
SET search_path = client1,global_schema;
你可以用这个。(一定要考虑)./P>
考虑一下这个小演示:
CREATE SCHEMA master; -- no access of others ..
CREATE SEQUENCE master.myseq; -- global sequence to have globally unique id
CREATE table master.tbl (
id int primary key DEFAULT nextval('master.myseq')
, foo text);
CREATE SCHEMA x;
CREATE table x.tbl() INHERITS (master.tbl);
INSERT INTO x.tbl(foo) VALUES ('x');
CREATE SCHEMA y;
CREATE table y.tbl() INHERITS (master.tbl);
INSERT INTO y.tbl(foo) VALUES ('y');
SELECT * FROM x.tbl; -- returns 'x'
SELECT * FROM y.tbl; -- returns 'y'
SELECT * FROM master.tbl; -- returns 'x' and 'y' <-- !!
-- clean it all up:
-- DROP SCHEMA x, y, master CASCADE;
结果:
id | foo | table_name
---+-----+-----------
2 | y | y.tbl
您可以从tableoid
派生源架构,最好是直接使用tableoid
查询系统目录。(显示的名称取决于search\u path
的设置)
这也比在许多单独的表中循环快得多。虽然我认为如果您可以重新构造表,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函数搜索包含名为\u tabname
的表的所有架构,以查找\u colname
中等于\u 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。如果有多个匹配项,结果将是其中一个,但无法保证是哪一个。如果要按字母顺序返回(比如)第一个,请在模式查询中添加一个orderby
子句。如果要返回所有匹配项,还可以对函数进行简单修改,以返回setoftext
和returnnext cur\u 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;
在这种情况下,它们共享相同的数据类型,但不共享任何数据;或通过像:
CREATE TABLE public.testtab ( searchval text );
CREATE TABLE a.testtab (LIKE public.testtab);
CREATE TABLE b.testtab (LIKE public.testtab);
在这种情况下,它们在创建后彼此完全不连接。据我所知,您要做的是搜索通过多个模型输入的字符串?像lets say用户输入“hello”,您希望在lets say模型中搜索此hello:汽车、公共汽车、自行车。我理解你的问题了吗?@Jonathanq:不,每个模式都是相同的,我想在同一个模型中查找数据,只是在不同的模式中:所以schema1.cars、schema2.cars、schema3.cars等等听起来很复杂。django处理PostgreSQL继承的能力如何?我不是django方面的专家,但这应该一点也不复杂。事实上,如果在许多模式中都有相同的表,则可以大大简化CREATE
脚本。需要明确的是:所有CREATE命令只能执行一次。但这很清楚,对吗?我忘记添加的内容(现在添加):如何识别源表。
CREATE TYPE public.testtab AS ( searchval text );
CREATE TABLE a.testtab OF public.testtab;
CREATE TABLE b.testtab OF public.testtab;
CREATE TABLE public.testtab ( searchval text );
CREATE TABLE a.testtab (LIKE public.testtab);
CREATE TABLE b.testtab (LIKE public.testtab);