Tengo una base de datos PostgreSQL 8.3 donde se usa la herencia de tablas. Me gustaría obtener una lista de todas las tablas junto con su nombre de esquema que se hereda de una tabla base mediante la consulta. ¿Hay alguna manera de que podamos obtener esto usando PGSQL?¿Cómo encontrar tablas heredadas de forma programática en PostgreSQL?
Respuesta
Dado que está en una versión tan antigua de PostgreSQL, probablemente tendrá que usar una función PL/PgSQL para manejar las profundidades de herencia de> 1. En PostgreSQL moderno (o incluso 8.4) usaría un común recursivo expresión de tabla (WITH RECURSIVE
).
La tabla pg_catalog.pg_inherits
es la clave. Teniendo en cuenta:
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 resultado correcto encontrará cc
, dd
y ccdd
, pero no encontrar notpp
o notshown
.
Una consulta de simple fondo es:
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;
... pero esto sólo encontrará cc
.
para la herencia multi-profundidad (es decir tableC
hereda tableB
hereda tableA
) tiene que extender que a través de un CTE recursiva o un bucle en PL/PgSQL, utilizando los hijos del último bucle como progenitores en la siguiente.
Actualización: Aquí hay una versión compatible con 8.3 que debe encontrar recursivamente todas las tablas que heredan directa o indirectamente de un padre determinado. Si se usa herencia múltiple, debe encontrar cualquier tabla que tenga la tabla de destino como uno de sus padres en cualquier punto del árbol.
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;
Uso:
regress=# SELECT * FROM find_children_of('pp'::regclass);
schemaname | tablename
------------+-----------
public | cc
public | dd
public | ccdd
(3 rows)
Aquí está la versión recursiva CTE, que funcionará si se actualiza Pg, pero no funcionará en su versión actual. Es mucho más limpio 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 siguiente instrucción recupera todas las tablas secundarias de la tabla 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
Se debe trabajar con un 8,3, aunque no estoy seguro al 100%.
Para aquellos que están ejecutando una versión de PostgreSQL con el apoyo RECURSIVE
aquí es una función que encuentra tablas para la tabla base especificada deriva.
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;
Es importante señalar que una mesa puede heredar múltiples tablas, y ninguna de las soluciones que se indican realmente exponer a eso; simplemente caminan por el árbol de un padre soltero. Considere:
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)
en cuenta que b no aparece en absoluto lo cual es incorrecto, ya que ambos ab_ y BA_ heredan b.
Sospecho que la "mejor" forma de manejar esto sería una columna que es texto [] y contiene (matriz [inhparent :: regclass]) :: texto para cada tabla. Eso le daría algo así como
inhrelid path
ab_ {"{a,b}"}
ba_ {"{b,a}"}
ab_ba_ {"{a,b}","{b,a}"}
Aunque obviamente no es lo ideal, que por lo menos expondría a la ruta de herencia completa y le permitirá acceder a él con suficientes gimnasia. Desafortunadamente, construir eso no es para nada fácil.
Una alternativa algo más simple es no incluir la ruta de herencia completa en cada nivel, solo cada tabla dirige a los padres. Eso le daría esto:
inhrelid parents
ab_ {a,b}
ba_ {b,a}
ab_ba_ {ab_,ba_}
- 1. Cuándo usar tablas heredadas en PostgreSQL?
- 2. Tablas temporales de PostgreSQL
- 3. ¿Cómo rechazar una llamada entrante de forma programática en android?
- 4. Cómo copio datos entre tablas PostgreSQL
- 5. agregue id de forma programática a R.id
- 6. ¿Cómo se leen las listas de SharePoint de forma programática?
- 7. ¿Cómo administro los archivos de registro WCF de forma programática?
- 8. Cómo recuperar información de forma programática desde LDAP
- 9. ¿Cómo acceder a los datos del portapapeles de forma programática?
- 10. Listar todas las tablas en postgresql information_schema
- 11. Android view layout_width - cómo cambiar de forma programática?
- 12. Establecer precio especial de forma programática en Magento
- 13. Ir a la pantalla de inicio de forma programática
- 14. Creación de programas de radio de forma programática
- 15. ¿Determinando de forma programática la causa de IOException?
- 16. Cómo encontrar el tamaño de una matriz en postgresql
- 17. Reiniciar PostgreSQL de forma remota
- 18. ¿Cómo se desactiva/se habilita 3G de forma programática en Android?
- 19. ¿Puedo determinar requisitos de interfaz/dependencias/herencia de forma programática?
- 20. ¿Existe alguna forma programática para identificar palabras reservadas de C#?
- 21. Compruebe de forma programática si el monitor está apagado
- 22. Cómo agregar instrucciones de impresión en cada función en archivos c de forma programática correcta?
- 23. JTree: Seleccionar todos los nodos de forma programática
- 24. ¿Cuál es la mejor manera de trabajar con datos de SQL Server de forma no programática?
- 25. Encontrar el valor hash de una fila en postgresql
- 26. ¿Cómo cambiar el esquema de múltiples tablas de PostgreSQL en una sola operación?
- 27. ¿Por qué PostgreSQL \ dt muestra solo tablas de esquema público?
- 28. cómo cambiar de forma programática la imagen de fondo en el formulario C#
- 29. Inicializando campos en clases heredadas
- 30. Cómo encontrar tablas no utilizadas en SQL Server
+1 por mencionar herencia múltiple. No pensé en eso. –
Esta es una gran consulta. ¡Solo traté de ejecutarlo y funcionó perfecto! Modifiqué esto para acomodar nuestras convenciones de nombres. Muchas gracias por esto ... – Arun
@Arun Me alegro de que haya ayudado. –