Ho un database 8.3 PostgreSQL in cui viene utilizzata l'ereditarietà delle tabelle. Vorrei ottenere un elenco di tutte le tabelle con il nome dello schema che è ereditato da una tabella di base tramite query. C'è un modo per ottenere questo usando PGSQL?Come trovare tabelle ereditate in modo programmatico in PostgreSQL?
risposta
Dato che si è in una versione precedente di PostgreSQL, probabilmente sarà necessario utilizzare una funzione PL/PgSQL per gestire profondità di ereditarietà di> 1. Su PostgreSQL moderno (o anche su 8.4) si utilizzerà un comune ricorsivo espressione della tabella (WITH RECURSIVE
).
La tabella pg_catalog.pg_inherits
è la chiave. Dato:
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
un risultato corretto troverà cc
, dd
, e ccdd
, ma non trovare notpp
o notshown
.
Una query singola profondità è:
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;
... ma questo sarà solo trovare cc
.
per il multi-profondità eredità (cioè tableC
eredita tableB
eredita tableA
) si deve estendere tale attraverso una CTE ricorsiva o un ciclo in PL/pgSQL, utilizzando i figli dell'ultimo ciclo come genitori nel prossimo.
Aggiornamento: Ecco una versione compatibile 8,3 che dovrebbe trovare in modo ricorsivo tutte le tabelle che ereditano direttamente o indirettamente da un determinato genitore. Se si utilizza l'ereditarietà multipla, dovrebbe trovare qualsiasi tabella che abbia la tabella di destinazione come uno dei suoi genitori in qualsiasi punto lungo l'albero.
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;
Usage:
regress=# SELECT * FROM find_children_of('pp'::regclass);
schemaname | tablename
------------+-----------
public | cc
public | dd
public | ccdd
(3 rows)
Ecco la versione ricorsiva CTE, che funzionerà se si aggiorna Pg, ma non funziona sulla versione corrente. È molto più pulito 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);
La seguente dichiarazione recupera tutte le tabelle figlio della tabella public.base_table_name
:
select bt.relname as table_name, bns.nspname as table_schema
from pg_class ct
join pg_namespace cns on ct.relnamespace = cns.oid and cns.nspname = 'public'
join pg_inherits i on i.inhparent = ct.oid and ct.relname = 'base_table_name'
join pg_class bt on i.inhrelid = bt.oid
join pg_namespace bns on bt.relnamespace = bns.oid
Dovrebbe funzionare con 8.3 anche se non sono sicuro al 100%.
Per coloro che sono in esecuzione una versione di PostgreSQL con RECURSIVE
supporto Ecco una funzione che trova derivata tavoli per la tabella di base specificata.
CREATE OR REPLACE FUNCTION tables_derived_from(base_namespace name, base_table name)
RETURNS TABLE (table_schema name, table_name name, oid oid)
AS $BODY$
WITH RECURSIVE inherited_id AS
(
SELECT i.inhrelid AS oid
FROM pg_inherits i
JOIN pg_class base_t ON i.inhparent = base_t.oid
JOIN pg_namespace base_ns ON base_t.relnamespace = base_ns.oid
WHERE base_ns.nspname = base_namespace AND base_t.relname = base_table
UNION
SELECT i.inhrelid AS oid
FROM pg_inherits i
JOIN inherited_id b ON i.inhparent = b.oid
)
SELECT child_ns.nspname as table_schema, child_t.relname as table_name, child_t.oid
FROM inherited_id i
JOIN pg_class child_t ON i.oid = child_t.oid
JOIN pg_namespace child_ns ON child_t.relnamespace = child_ns.oid
ORDER BY 1, 2, 3;
$BODY$ LANGUAGE sql STABLE;
E 'importante notare che una tabella può ereditare più tabelle, e nessuna delle soluzioni elencate in realtà esporre quello; camminano semplicemente lungo l'albero di un genitore single. Considerate:
CREATE TABLE a();
CREATE TABLE b();
CREATE TABLE ab_() INHERITS (a,b);
CREATE TABLE ba_() INHERITS (b,a);
CREATE TABLE ab__() INHERITS (ab_);
CREATE TABLE ba__() INHERITS (ba_);
CREATE TABLE ab_ba_() INHERITS (ab_, ba_);
CREATE TABLE ba_ab_() INHERITS (ba_, ab_);
WITH RECURSIVE inh AS (
SELECT i.inhparent::regclass, i.inhrelid::regclass, i.inhseqno FROM pg_catalog.pg_inherits i WHERE inhparent = 'a'::regclass
UNION
SELECT i.inhparent::regclass, i.inhrelid::regclass, i.inhseqno FROM inh INNER JOIN pg_catalog.pg_inherits i ON (inh.inhrelid = i.inhparent)
) SELECT * FROM inh;
inhparent | inhrelid | inhseqno
-----------+----------+----------
a | ab_ | 1
a | ba_ | 2
ab_ | ab__ | 1
ba_ | ba__ | 1
ab_ | ab_ba_ | 1
ba_ | ab_ba_ | 2
ba_ | ba_ab_ | 1
ab_ | ba_ab_ | 2
(8 rows)
noti che b non si presenta affatto che non è corretto, sia come ab_ e ba_ ereditare b.
Sospetto che il modo "migliore" per gestirlo sia una colonna che è text [] e contiene (array [inhparent :: regclass]) :: text per ogni tabella. Ciò darà qualcosa di simile
inhrelid path
ab_ {"{a,b}"}
ba_ {"{b,a}"}
ab_ba_ {"{a,b}","{b,a}"}
Mentre ovviamente non è l'ideale, che avrebbe almeno esporre il percorso di successione completa e permetterà di accedere con abbastanza ginnastica. Sfortunatamente, la costruzione di questo non è affatto facile.
Un'alternativa un po 'più semplice non è quella di includere il percorso di ereditarietà completo a ogni livello, solo che ogni tabella indirizza i genitori. Questo ti darebbe questo:
inhrelid parents
ab_ {a,b}
ba_ {b,a}
ab_ba_ {ab_,ba_}
- 1. Chiave esterna + ereditarietà di tabelle in PostgreSQL?
- 2. Elenca tabelle in uno schema PostgreSQL
- 3. evidenzia in modo programmatico UIBarButtonItem
- 4. Come si crea ColorStateList in modo programmatico?
- 5. Come impostare alcune imeOptions in modo programmatico
- 6. Come creare NSPopover in modo programmatico
- 7. Come utilizzare in modo programmatico Spring's JdbcTemplate?
- 8. Come avviare un'istanza Amazon EC2 in modo programmatico in .NET
- 9. Stampa tabelle e relazioni dalle tabelle Postgresql
- 10. Come ottenere il numero totale di tabelle in postgresql?
- 11. Come trovare le applicazioni attualmente in esecuzione in modo programmatico su Android?
- 12. Come imposto in modo programmatico le proprietà delle tabelle predefinite per CKEditor?
- 13. Creare in modo programmatico connessioni ODBC e tabelle di collegamento in MS Access
- 14. Come rilasciare più tabelle in PostgreSQL utilizzando un carattere jolly
- 15. Come visualizzare le tabelle del database in postgresql usando pgAdmin?
- 16. Come creare trigger per tutte le tabelle in postgresql?
- 17. Come posiziono una tela in modo programmatico in Silverlight?
- 18. Come chiudere in sicurezza Google Chrome in modo programmatico
- 19. Come creare i blocchi logici in modo programmatico in Blender?
- 20. Come impostare la gravità in modo programmatico in un relativelayout
- 21. Come trasformare il gruppo in file SVG in modo programmatico?
- 22. Creazione di viste in modo programmatico in IOS (come funziona)?
- 23. Come posso autenticare un utente in modo programmatico in Django?
- 24. Come faccio a impostare in modo programmatico gzip in Jetty?
- 25. Come ottenere nUnità delle categorie selezionate in modo programmatico
- 26. Come scaricare un jar usando Maven in modo programmatico
- 27. Avvia Silverlight dall'app browser in modo programmatico
- 28. Posso impostare android: layout_toLeftOf in modo programmatico?
- 29. Come eseguire il flash su Genymotion in modo programmatico
- 30. Evidenziare in modo programmatico la cella UITableView
+1 per menzionare l'ereditarietà multipla. Non ci ho pensato. –
Questa è un'ottima query. Ho appena provato ad eseguirlo e ha funzionato perfettamente !! L'ho modificato per adattare le nostre convenzioni di denominazione. Grazie mille per questo ... – Arun
@Arun Li ho contenti. –