PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да намеря програмно наследени таблици в PostgreSQL?

Тъй като използвате толкова стара версия на PostgreSQL, вероятно ще трябва да използвате PL/PgSQL функция, за да обработвате дълбочини на наследяване от> 1. В съвременния PostgreSQL (или дори 8.4) бихте използвали рекурсивен израз на обща таблица (WITH RECURSIVE ).

pg_catalog.pg_inherits масата е ключът. Дадено:

create table pp( );     -- The parent we'll search for
CREATE TABLE notpp(); -- Another root for multiple inheritance
create table cc( ) inherits (pp); -- a 1st level child of pp
create table dd( ) inherits (cc,notpp); -- a 2nd level child of pp that also inherits aa
create table notshown( ) inherits (notpp); -- Table that inherits only notpp
create table ccdd () inherits (cc,dd) -- Inheritance is a graph not a tree; join node

Правилен резултат ще намери cc , dd и ccdd , но не намира notpp или notshown .

Заявка с една дълбочина е:

SELECT pg_namespace.nspname, pg_class.relname 
FROM pg_catalog.pg_inherits 
  INNER JOIN pg_catalog.pg_class ON (pg_inherits.inhrelid = pg_class.oid) 
  INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid) 
WHERE inhparent = 'pp'::regclass;

... но това ще намери само cc .

За наследяване с множество дълбочини (т.е. tableC наследява tableB наследява tableA ) трябва да го разширите чрез рекурсивен CTE или цикъл в PL/PgSQL, като използвате децата на последния цикъл като родители в следващия.

Актуализация :Ето 8.3 съвместима версия, която трябва рекурсивно да намира всички таблици, които наследяват пряко или косвено от даден родител. Ако се използва множествено наследяване, трябва да се намери всяка таблица, която има целевата таблица като един от своите родители във всяка точка от дървото.

CREATE OR REPLACE FUNCTION find_children(oid) RETURNS SETOF oid as $$
SELECT i.inhrelid FROM pg_catalog.pg_inherits i WHERE i.inhparent = $1
UNION
SELECT find_children(i.inhrelid) FROM pg_catalog.pg_inherits i WHERE i.inhparent = $1;
$$ LANGUAGE 'sql' STABLE;

CREATE OR REPLACE FUNCTION find_children_of(parentoid IN regclass, schemaname OUT name, tablename OUT name) RETURNS SETOF record AS $$
SELECT pg_namespace.nspname, pg_class.relname 
        FROM find_children($1) inh(inhrelid) 
          INNER JOIN pg_catalog.pg_class ON (inh.inhrelid = pg_class.oid) 
          INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid);
$$ LANGUAGE 'sql' STABLE;

Употреба:

regress=# SELECT * FROM find_children_of('pp'::regclass);
 schemaname | tablename 
------------+-----------
 public     | cc
 public     | dd
 public     | ccdd
(3 rows)

Ето рекурсивната CTE версия, която ще работи, ако актуализирате Pg, но няма да работи на текущата ви версия. Много по-чисто е IMO.

WITH RECURSIVE inh AS (
        SELECT i.inhrelid FROM pg_catalog.pg_inherits i WHERE inhparent = 'pp'::regclass
        UNION
        SELECT i.inhrelid FROM inh INNER JOIN pg_catalog.pg_inherits i ON (inh.inhrelid = i.inhparent)
)
SELECT pg_namespace.nspname, pg_class.relname 
    FROM inh 
      INNER JOIN pg_catalog.pg_class ON (inh.inhrelid = pg_class.oid) 
      INNER JOIN pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ltree модулът на PostgreSQL подходящ ли е за резбови коментари?

  2. попълнете колона с последната стойност от дяла в postgresql

  3. Моите любими разширения на PostgreSQL - първа част

  4. PostgreSQL - накарайте две транзакции да се изпълняват едновременно

  5. Опресняване на материализирани изгледи:паралелност, транзакционно поведение