Postgres: SQL para enumerar las claves externas de la tabla

219

¿Hay alguna manera de usar SQL para enumerar todas las claves foráneas para una tabla dada? Sé el nombre / esquema de la tabla y puedo conectarlo.

smack0007
fuente
Sugiero usar la respuesta de @Magnus . Más simple, más limpio, más rápido.
Erwin Brandstetter

Respuestas:

373

Puede hacerlo a través de las tablas de información_esquema. Por ejemplo:

SELECT
    tc.table_schema, 
    tc.constraint_name, 
    tc.table_name, 
    kcu.column_name, 
    ccu.table_schema AS foreign_table_schema,
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
      AND tc.table_schema = kcu.table_schema
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
      AND ccu.table_schema = tc.table_schema
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='mytable';
ollyc
fuente
8
table_name = 'mytable' debe ser tc.table_name = 'mytable' o, de lo contrario, arroja un error ambiguo
intrepion
15
+1, muy útil. Para hacer la consulta más robusta, probablemente también debería unirse en restrictint_schema, ya que es posible que dos esquemas tengan restricciones con el mismo nombre. Algo así como: FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu USING (constraint_schema, constraint_name) JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
EMP
8
Esto se rompe cuando hay varias columnas en una restricción, ¿no? Parece que no hay una forma adecuada de asociar columnas pk con columnas fk utilizando information_schema BTW.
fionbio 01 de
55
De hecho, se rompe con más de una columna en restricción. Para Postgres, hay una manera de obtener esta información del esquema pg_catalog. Vea mi respuesta a continuación.
Martin
99
La consulta es incorrecta. Se supone que los nombres de restricción no pueden repetirse, lo cual es falso. Las restricciones con el mismo nombre pueden existir en diferentes espacios de nombres. Estás utilizando restrict_name para hacer la unión. Además, unirse tanto en restrictint_name como en schema name no funcionará, ya que no está seguro de que las dos restricciones sean las mismas. La única opción es ir a pg_constraints, pg_class, etc. usando oids para unirse. El catálogo ANSI de Postgres solo está allí para el cumplimiento, pero es defectuoso. pg_catalog es el camino a seguir. La respuesta correcta está aquí dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova
69

psql hace esto, y si comienzas psql con:

psql -E

le mostrará exactamente qué consulta se ejecuta. En el caso de encontrar claves foráneas, es:

SELECT conname,
  pg_catalog.pg_get_constraintdef(r.oid, true) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid = '16485' AND r.contype = 'f' ORDER BY 1

En este caso, 16485 es el oid de la tabla que estoy viendo, puede obtenerlo simplemente lanzando su nombre de tabla para volver a clasificar como:

WHERE r.conrelid = 'mytable'::regclass

Esquema: califique el nombre de la tabla si no es único (o el primero en su search_path):

WHERE r.conrelid = 'myschema.mytable'::regclass
Magnus Hagander
fuente
2
¡Esto es muy útil! Postgres parece tener un millón de pequeñas funciones como esta que simplifican todo. ¿Ahora cómo recordarlos?
epic_fil
55
@ Phil: Solo necesitas una idea general. Deje que el manual recuerde el resto.
Erwin Brandstetter
3
para enumerar todas las claves externas que apuntan a una mesa:SELECT conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.confrelid = 'myschema.mytable'::regclass;
regilero
1
@ErwinBrandstetter ¿cómo hago para obtener un nombre de tabla extranjera?
Wellington Silva Ribeiro
2
No lo entiendo, ¿qué comando se debe usar? psql -E -U username -d database ThenWHAT?
Poutrathor
49

Emitir \d+ tablenameen el indicador de PostgreSQL, además de mostrar los tipos de datos de la columna de la tabla, mostrará los índices y las claves externas.

Gre Hahn
fuente
Lo siento, no noté que mi comentario fue recortado. Si al menos pudiera intentarlo una vez, vería que también se muestran las asignaciones de claves externas.
Gre Hahn
45

La respuesta de Ollyc es buena ya que no es específica de Postgres, sin embargo, se descompone cuando la clave externa hace referencia a más de una columna. La siguiente consulta funciona para un número arbitrario de columnas, pero depende en gran medida de las extensiones de Postgres:

select 
    att2.attname as "child_column", 
    cl.relname as "parent_table", 
    att.attname as "parent_column",
    conname
from
   (select 
        unnest(con1.conkey) as "parent", 
        unnest(con1.confkey) as "child", 
        con1.confrelid, 
        con1.conrelid,
        con1.conname
    from 
        pg_class cl
        join pg_namespace ns on cl.relnamespace = ns.oid
        join pg_constraint con1 on con1.conrelid = cl.oid
    where
        cl.relname = 'child_table'
        and ns.nspname = 'child_schema'
        and con1.contype = 'f'
   ) con
   join pg_attribute att on
       att.attrelid = con.confrelid and att.attnum = con.child
   join pg_class cl on
       cl.oid = con.confrelid
   join pg_attribute att2 on
       att2.attrelid = con.conrelid and att2.attnum = con.parent
martín
fuente
antes de 8.4, la función unnest debe crearse al principio. wiki.postgresql.org/wiki/Array_Unnest
maletin
¿Dónde se inserta el nombre de la tabla en esta consulta? Ingresado textualmente, lo anterior devuelve 0 filas en mi base de datos PSQL que tiene decenas de claves foráneas.
Phrogz
44
Reemplaza 'child_table' y 'child_schema' con los nombres de la tabla y su esquema
martin
esto no te dice el nombre de la llave.
Evan Carroll
@EvanCarroll He actualizado mi respuesta para incluir el nombre de la clave.
Martin
31

Extensión a la receta ollyc:

CREATE VIEW foreign_keys_view AS
SELECT
    tc.table_name, kcu.column_name,
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name
FROM
    information_schema.table_constraints AS tc
    JOIN information_schema.key_column_usage 
        AS kcu ON tc.constraint_name = kcu.constraint_name
    JOIN information_schema.constraint_column_usage 
        AS ccu ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY';

Luego:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';

Mvoicem
fuente
Gracias, ideal para reutilizar.
schellingerht
16

revise la publicación ff para su solución y no olvide marcar esto cuando esté bien

http://errorbank.blogspot.com/2011/03/list-all-foreign-keys-references-for.html

SELECT
  o.conname AS constraint_name,
  (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema,
  m.relname AS source_table,
  (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column,
  (SELECT nspname FROM pg_namespace WHERE oid=f.relnamespace) AS target_schema,
  f.relname AS target_table,
  (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column
FROM
  pg_constraint o LEFT JOIN pg_class f ON f.oid = o.confrelid LEFT JOIN pg_class m ON m.oid = o.conrelid
WHERE
  o.contype = 'f' AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r');
Sheldon
fuente
Ofrece dos SQL que funcionan en PostgreSQL 9.1 (una vez que corrija el escape incorrecto ponga su 'nombre de tabla' (sin prefijo de esquema) en el SQL).
alfonx
2
+1: esta es la única solución que no devuelve duplicados.
Olivier MATROT
para esta solución, funciona bien y no devuelve duplicados.
Fuhrmann
1
Esta solución solo mostrará la primera columna de las claves foráneas de varias columnas ... pero parece mucho más simple que la que acabo de publicar que hará múltiplos.
dewin
12

Esta consulta funciona correctamente con claves compuestas también:

select c.constraint_name
    , x.table_schema as schema_name
    , x.table_name
    , x.column_name
    , y.table_schema as foreign_schema_name
    , y.table_name as foreign_table_name
    , y.column_name as foreign_column_name
from information_schema.referential_constraints c
join information_schema.key_column_usage x
    on x.constraint_name = c.constraint_name
join information_schema.key_column_usage y
    on y.ordinal_position = x.position_in_unique_constraint
    and y.constraint_name = c.unique_constraint_name
order by c.constraint_name, x.ordinal_position
oscavi
fuente
2
Se está uniendo a las columnas en "restrict_name", por lo que esto solo funcionará si todos sus nombres de restricción son únicos (en todas las tablas en todos los esquemas). Esto no suele ser un requisito y, por lo tanto, la base de datos no lo exige.
Zilk
3
Gracias. Esta es la única respuesta que muestra cómo utilizar information_schema para manejar correctamente varias columnas.
Samuel Danielson
Esta solución funciona No produce duplicados y maneja múltiples campos en el FK.
Igor
9

Creo que lo que estabas buscando y muy cerca de lo que escribió @ollyc es esto:

SELECT
tc.constraint_name, tc.table_name, kcu.column_name, 
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name 
FROM 
information_schema.table_constraints AS tc 
JOIN information_schema.key_column_usage AS kcu
  ON tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage AS ccu
  ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' AND ccu.table_name='YourTableNameHere';

Esto enumerará todas las tablas que usan la tabla especificada como clave externa

Shaun McCready
fuente
9

voto corto pero dulce si funciona para ti.

select  * from information_schema.key_column_usage where constraint_catalog=current_catalog and table_name='your_table_name' and position_in_unique_constraint notnull;
NikhilP
fuente
Funcionó un encanto mientras escribo con PG 12.2
Jack Kinsella
5

Ninguna de las respuestas existentes me dio resultados en la forma en que realmente los quería. Así que aquí está mi consulta (gigantesca) para encontrar información sobre claves foráneas.

Algunas notas

  • Las expresiones utilizadas para generar from_colsy to_colspodrían simplificarse enormemente en Postgres 9.4 y posteriores usando en WITH ORDINALITYlugar del hacker de uso de funciones de ventana que estoy usando.
  • Esas mismas expresiones dependen de que el planificador de consultas no altere el orden de resultados devuelto UNNEST. No creo que lo haga, pero no tengo claves externas de varias columnas en mi conjunto de datos para probar. Agregar las sutilezas 9.4 elimina esta posibilidad por completo.
  • La consulta en sí requiere Postgres 9.0 o posterior (8.x no permitió ORDER BYen funciones agregadas)
  • Reemplace STRING_AGGcon ARRAY_AGGsi desea una matriz de columnas en lugar de una cadena separada por comas.

-

SELECT
    c.conname AS constraint_name,
    (SELECT n.nspname FROM pg_namespace AS n WHERE n.oid=c.connamespace) AS constraint_schema,

    tf.name AS from_table,
    (
        SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq)
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
                    attnum
                FROM
                    UNNEST(c.conkey) AS t(attnum)
            ) AS t
            INNER JOIN pg_attribute AS a ON a.attrelid=c.conrelid AND a.attnum=t.attnum
    ) AS from_cols,

    tt.name AS to_table,
    (
        SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq)
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
                    attnum
                FROM
                    UNNEST(c.confkey) AS t(attnum)
            ) AS t
            INNER JOIN pg_attribute AS a ON a.attrelid=c.confrelid AND a.attnum=t.attnum
    ) AS to_cols,

    CASE confupdtype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_update,
    CASE confdeltype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_delete,
    CASE confmatchtype::text WHEN 'f' THEN 'full' WHEN 'p' THEN 'partial' WHEN 'u' THEN 'simple' WHEN 's' THEN 'simple' ELSE NULL END AS match_type,  -- In earlier postgres docs, simple was 'u'nspecified, but current versions use 's'imple.  text cast is required.

    pg_catalog.pg_get_constraintdef(c.oid, true) as condef
FROM
    pg_catalog.pg_constraint AS c
    INNER JOIN (
        SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name
        FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
    ) AS tf ON tf.oid=c.conrelid
    INNER JOIN (
        SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name
        FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
    ) AS tt ON tt.oid=c.confrelid
WHERE c.contype = 'f' ORDER BY 1;
dewin
fuente
5

De otra manera:

WITH foreign_keys AS (
    SELECT
      conname,
      conrelid,
      confrelid,
      unnest(conkey)  AS conkey,
      unnest(confkey) AS confkey
    FROM pg_constraint
    WHERE contype = 'f' -- AND confrelid::regclass = 'your_table'::regclass
)
-- if confrelid, conname pair shows up more than once then it is multicolumn foreign key
SELECT fk.conname as constraint_name,
       fk.confrelid::regclass as referenced_table, af.attname as pkcol,
       fk.conrelid::regclass as referencing_table, a.attname as fkcol
FROM foreign_keys fk
JOIN pg_attribute af ON af.attnum = fk.confkey AND af.attrelid = fk.confrelid
JOIN pg_attribute a ON a.attnum = conkey AND a.attrelid = fk.conrelid
ORDER BY fk.confrelid, fk.conname
;
Konrad Perzyna
fuente
4

Utilice el nombre de la clave primaria a la que hacen referencia las claves y consulte el esquema de información:

select table_name, column_name
from information_schema.key_column_usage
where constraint_name IN (select constraint_name
  from information_schema.referential_constraints 
  where unique_constraint_name = 'TABLE_NAME_pkey')

Aquí 'TABLE_NAME_pkey' es el nombre de la Clave primaria referenciada por las Claves externas.

markmnl
fuente
4

Aquí hay una solución de Andreas Joseph Krogh de la lista de correo de PostgreSQL: http://www.postgresql.org/message-id/[email protected]

SELECT source_table::regclass, source_attr.attname AS source_column,
    target_table::regclass, target_attr.attname AS target_column
FROM pg_attribute target_attr, pg_attribute source_attr,
  (SELECT source_table, target_table, source_constraints[i] source_constraints, target_constraints[i] AS target_constraints
   FROM
     (SELECT conrelid as source_table, confrelid AS target_table, conkey AS source_constraints, confkey AS target_constraints,
       generate_series(1, array_upper(conkey, 1)) AS i
      FROM pg_constraint
      WHERE contype = 'f'
     ) query1
  ) query2
WHERE target_attr.attnum = target_constraints AND target_attr.attrelid = target_table AND
      source_attr.attnum = source_constraints AND source_attr.attrelid = source_table;

Esta solución maneja claves foráneas que hacen referencia a múltiples columnas y evita duplicados (que algunas de las otras respuestas no pueden hacer). Lo único que cambié fueron los nombres de las variables.

Aquí hay un ejemplo que devuelve todas las employeecolumnas que hacen referencia a la permissiontabla:

SELECT source_column
FROM foreign_keys
WHERE source_table = 'employee'::regclass AND target_table = 'permission'::regclass;
Gili
fuente
4

Para ampliar la excelente respuesta de Martin, aquí hay una consulta que le permite filtrar en función de la tabla principal y le muestra el nombre de la tabla secundaria con cada tabla principal para que pueda ver todas las tablas / columnas dependientes en función de las restricciones de clave externa en La mesa principal.

select 
    con.constraint_name,
    att2.attname as "child_column", 
    cl.relname as "parent_table", 
    att.attname as "parent_column",
    con.child_table,
    con.child_schema
from
   (select 
        unnest(con1.conkey) as "parent", 
        unnest(con1.confkey) as "child", 
        con1.conname as constraint_name,
        con1.confrelid, 
        con1.conrelid,
        cl.relname as child_table,
        ns.nspname as child_schema
    from 
        pg_class cl
        join pg_namespace ns on cl.relnamespace = ns.oid
        join pg_constraint con1 on con1.conrelid = cl.oid
    where  con1.contype = 'f'
   ) con
   join pg_attribute att on
       att.attrelid = con.confrelid and att.attnum = con.child
   join pg_class cl on
       cl.oid = con.confrelid
   join pg_attribute att2 on
       att2.attrelid = con.conrelid and att2.attnum = con.parent
   where cl.relname like '%parent_table%'       
Cervo
fuente
1
La consulta en la respuesta aceptada agrega 1.2 segundos a una consulta de ~ 0.03, la suya agrega solo 0.01, ¡gracias!
AVProgrammer
3

Solución adecuada al problema, utilizando information_schema, trabajando con claves de múltiples columnas, uniendo columnas de diferentes nombres en ambas tablas correctamente y también compatibles con ms sqlsever:

select fks.TABLE_NAME as foreign_key_table_name
, fks.CONSTRAINT_NAME as foreign_key_constraint_name
, kcu_foreign.COLUMN_NAME as foreign_key_column_name
, rc.UNIQUE_CONSTRAINT_NAME as primary_key_constraint_name
, pks.TABLE_NAME as primary_key_table_name
, kcu_primary.COLUMN_NAME as primary_key_column_name
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS fks -- foreign keys
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu_foreign -- the columns of the above keys
    on fks.TABLE_CATALOG = kcu_foreign.TABLE_CATALOG
    and fks.TABLE_SCHEMA = kcu_foreign.TABLE_SCHEMA
    and fks.TABLE_NAME = kcu_foreign.TABLE_NAME
    and fks.CONSTRAINT_NAME = kcu_foreign.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc -- referenced constraints
    on rc.CONSTRAINT_CATALOG = fks.CONSTRAINT_CATALOG
    and rc.CONSTRAINT_SCHEMA = fks.CONSTRAINT_SCHEMA
    and rc.CONSTRAINT_NAME = fks.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS pks -- primary keys (referenced by fks)
    on rc.UNIQUE_CONSTRAINT_CATALOG = pks.CONSTRAINT_CATALOG
    and rc.UNIQUE_CONSTRAINT_SCHEMA = pks.CONSTRAINT_SCHEMA
    and rc.UNIQUE_CONSTRAINT_NAME = pks.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu_primary
    on pks.TABLE_CATALOG = kcu_primary.TABLE_CATALOG
    and pks.TABLE_SCHEMA = kcu_primary.TABLE_SCHEMA
    and pks.TABLE_NAME = kcu_primary.TABLE_NAME
    and pks.CONSTRAINT_NAME = kcu_primary.CONSTRAINT_NAME
    and kcu_foreign.ORDINAL_POSITION = kcu_primary.ORDINAL_POSITION -- this joins the columns
where fks.TABLE_SCHEMA = 'dbo' -- replace with schema name
and fks.TABLE_NAME = 'your_table_name' -- replace with table name
and fks.CONSTRAINT_TYPE = 'FOREIGN KEY'
and pks.CONSTRAINT_TYPE = 'PRIMARY KEY'
order by fks.constraint_name, kcu_foreign.ORDINAL_POSITION

Nota: Existen algunas diferencias entre las implementaciones de potgresql y sqlserver information_schemaque hacen que la respuesta superior dé resultados diferentes en los dos sistemas: una muestra los nombres de columna para la tabla de clave externa y la otra para la tabla de clave primaria. Por esta razón, decidí usar la vista KEY_COLUMN_USAGE en su lugar.

jakubiszon
fuente
El esquema de información parece ser la respuesta correcta, pero realmente desea las tablas pg_catalog: pg_constraint, etc. Nos mordió mucho esto. si su base de datos tiene grandes restricciones, puede haber problemas de rendimiento ...
hajikelist
La condición anterior en ORDINAL_POSITIONpuede producir un resultado incorrecto cuando el orden de las columnas en la clave externa es diferente del orden de las columnas en la restricción única. Creo que debería haber acompañado en kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Actualización : También, una clave externa puede depender de una restricción UNIQUE, así que creo que debería quitar el pks.CONSTRAINT_TYPEestado y solo puede unirse rca kcu_primarydirectamente
EASD
He hecho una respuesta similar aquí: stackoverflow.com/a/62260908/9093051
easd
2
SELECT r.conname
      ,ct.table_name
      ,pg_catalog.pg_get_constraintdef(r.oid, true) as condef
  FROM pg_catalog.pg_constraint r, information_schema.constraint_table_usage ct
 WHERE r.contype = 'f' 
   AND r.conname = ct.constraint_name
 ORDER BY 1
Pugazendhi Asaimuthu
fuente
2

Escribí una solución que me gusta y uso con frecuencia. El código está en http://code.google.com/p/pgutils/ . Vea la vista pgutils.foreign_keys.

Desafortunadamente, el resultado es demasiado extenso para incluirlo aquí. Sin embargo, puede probarlo en una versión pública de la base de datos aquí, así:

$ psql -h unison-db.org -U PUBLIC -d unison -c 'select * from pgutils.foreign_keys;

Esto funciona con 8.3 al menos. Anticipo actualizarlo, si es necesario, en los próximos meses.

-Reece

Reece
fuente
1
El enlace del proyecto ahora está muerto.
pimlottc
@pimlottc: movido a bitbucket.org/reece/pgutils . Gracias por señalar esto.
Reece
0

Nota: ¡No olvide el orden de las columnas mientras lee las columnas de restricción!

SELECT conname, attname
  FROM pg_catalog.pg_constraint c 
  JOIN pg_catalog.pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY (c.conkey)
 WHERE attrelid = 'schema.table_name'::regclass
 ORDER BY conname, array_position(c.conkey, a.attnum)
Nashev
fuente
0

Esto es lo que estoy usando actualmente, enumerará una tabla y sus restricciones fkey [eliminar la cláusula de tabla y enumerará todas las tablas en el catálogo actual]:

SELECT

    current_schema() AS "schema",
    current_catalog AS "database",
    "pg_constraint".conrelid::regclass::text AS "primary_table_name",
    "pg_constraint".confrelid::regclass::text AS "foreign_table_name",

    (
        string_to_array(
            (
                string_to_array(
                    pg_get_constraintdef("pg_constraint".oid),
                    '('
                )
            )[2],
            ')'
        )
    )[1] AS "foreign_column_name",

    "pg_constraint".conindid::regclass::text AS "constraint_name",

    TRIM((
        string_to_array(
            pg_get_constraintdef("pg_constraint".oid),
            '('
        )
    )[1]) AS "constraint_type",

    pg_get_constraintdef("pg_constraint".oid) AS "constraint_definition"

FROM pg_constraint AS "pg_constraint"

JOIN pg_namespace AS "pg_namespace" ON "pg_namespace".oid = "pg_constraint".connamespace

WHERE
    --fkey and pkey constraints
    "pg_constraint".contype IN ( 'f', 'p' )
    AND
    "pg_namespace".nspname = current_schema()
    AND
    "pg_constraint".conrelid::regclass::text IN ('whatever_table_name')
hajikelist
fuente
0

la respuesta más rápida para verificar directamente en bash basada completamente en esta respuesta

IFS='' read -r -d '' sql_code << EOF_SQL_CODE
      SELECT
      o.oid
      , o.conname AS constraint_name
      , (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema
      , m.relname AS source_table
      , (SELECT a.attname FROM pg_attribute a
      WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column
      , (SELECT nspname FROM pg_namespace
      WHERE oid=f.relnamespace) AS target_schema
      , f.relname AS target_table
      , (SELECT a.attname FROM pg_attribute a
      WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column
      , ROW_NUMBER () OVER (ORDER BY o.oid) as rowid
      FROM pg_constraint o
      LEFT JOIN pg_class f ON f.oid = o.confrelid
      LEFT JOIN pg_class m ON m.oid = o.conrelid
      WHERE 1=1
      AND o.contype = 'f'
      AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r')
EOF_SQL_CODE

psql -d my_db -c "$sql_code"
Yordan Georgiev
fuente