Postgres: SQL для отображения внешних ключей таблицы

221

Есть ли способ использовать SQL для отображения всех внешних ключей для данной таблицы? Я знаю имя таблицы / схему, и я могу подключить это.

smack0007
источник
Я предлагаю использовать ответ @Magnus . Самый простой, самый чистый, самый быстрый.
Эрвин Брандштеттер,

Ответы:

378

Вы можете сделать это через таблицы information_schema. Например:

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
источник
8
table_name = 'mytable' должен быть tc.table_name = 'mytable', иначе он выдаст неоднозначную ошибку
intrepion
15
+1, очень полезно. Чтобы сделать запрос более устойчивым, он, вероятно, должен также присоединиться к constraint_schema, так как две схемы могут иметь ограничения с одинаковым именем. Что-то вроде: 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
Это нарушается, когда в ограничении несколько столбцов, не так ли? Кажется, не существует подходящего способа связать столбцы pk со столбцами fk, используя BTW information_schema.
fionbio
5
Это действительно ломается с более чем одним столбцом в ограничении. Для Postgres есть способ получить эту информацию из схемы pg_catalog. Смотрите мой ответ ниже.
Мартин
9
Запрос неверный. Предполагается, что имена ограничений не могут повторяться, что неверно. Ограничения с одним и тем же именем могут существовать в разных пространствах имен. Вы используете ограничение_имя, чтобы сделать соединение. Также не сработает объединение как по имени-ограничениям, так и по имени схемы, поскольку вы не уверены, что эти два ограничения одинаковы. Единственный вариант для pg_constraints, pg_class и т. Д. С использованием oids для объединения. Каталог ANSI Postgres только для соответствия, но он имеет недостатки. pg_catalog это путь. Правильный ответ здесь: dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Тулин Кордова,
69

PSQL делает это, и если вы запускаете PSQL с:

psql -E

он покажет вам, какой запрос выполняется. В случае поиска внешних ключей это:

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

В данном случае 16485 - это oid таблицы, на которую я смотрю - вы можете получить ее, просто приведя свое имя таблицы к классу переклассификации следующим образом:

WHERE r.conrelid = 'mytable'::regclass

Укажите имя таблицы, если оно не уникальное (или первое в вашей таблице search_path):

WHERE r.conrelid = 'myschema.mytable'::regclass
Магнус Хагандер
источник
2
Это очень удобно! У Postgres, кажется, есть миллион таких маленьких функций, которые делают все проще. Теперь, как их запомнить?
epic_fil
5
@Phil: Вам нужна только общая идея. Пусть руководство запомнит все остальное.
Эрвин Брандштеттер
3
перечислить все внешние ключи для таблицы: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 20.10.15
1
@ErwinBrandstetter, как мне сделать, чтобы получить имя иностранной таблицы?
Веллингтон Сильва Рибейро
2
Я не понимаю, какую команду следует использовать? psql -E -U username -d database ThenWHAT?
Poutrathor
49

Проблема \d+ tablenameв приглашении PostgreSQL, помимо отображения типов данных столбца таблицы, он покажет индексы и внешние ключи.

Гре Хан
источник
Извините, не заметил, что мой комментарий обрезан. Если бы вы хотя бы попытались сделать это один раз, вы бы увидели отображение внешних ключей.
Гре Хан
45

Ответ Оллика хорош, так как он не специфичен для Postgres, однако он ломается, когда внешний ключ ссылается более чем на один столбец. Следующий запрос работает для произвольного числа столбцов, но он сильно зависит от расширений 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
Мартин
источник
до 8.4 необходимо сначала создать функцию unnest. wiki.postgresql.org/wiki/Array_Unnest
maletin
Где вставить имя таблицы в этот запрос? Введенный дословно, выше возвращает 0 строк в моей PSQL БД, которая имеет десятки внешних ключей.
Phrogz
4
Вы заменяете 'child_table' и 'child_schema' именами таблицы и ее схемы
Март
это не говорит вам имя Fkey.
Эван Кэрролл
@EvanCarroll Я обновил свой ответ, включив в него название ключа.
мартин
31

Дополнение к рецепту оллика:

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';

Затем:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';

Mvoicem
источник
Спасибо, идеально подходит для повторного использования.
schellingerht
16

проверьте ff сообщение для вашего решения и не забудьте отметить это, когда вы штрафуете это полезно

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');
Шелдон
источник
Предлагает два SQL, которые работают на PostgreSQL 9.1 (как только вы исправите неправильное экранирование, поместите свое «имя таблицы» (без префикса схемы) в SQL).
alfonx
2
+1: это единственное решение, которое не возвращает дубликаты.
Оливье МАТРО
к этому решению, работает нормально и не возвращает дубликаты.
Fuhrmann
1
Это решение покажет только первый столбец любых внешних столбцов с несколькими столбцами ... но выглядит намного проще, чем тот, который я только что опубликовал, который будет делать кратные.
Девин
12

Этот запрос корректно работает с составными ключами также:

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
источник
2
Вы объединяете столбцы с именем "constraint_name", поэтому это будет работать только в том случае, если все ваши имена ограничений уникальны (для всех таблиц во всех схемах). Обычно это не является обязательным требованием и, следовательно, не обеспечивается базой данных.
Zilk
3
Спасибо. Это единственный ответ, который показывает, как использовать information_schema для правильной обработки нескольких столбцов.
Самуэль Дэниелсон
Это решение работает. Он не создает дубликатов и обрабатывает несколько полей в FK.
Игорь
9

Я думаю, что вы искали и очень близко к тому, что написал @ollyc, это:

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';

Это перечислит все таблицы, которые используют вашу указанную таблицу в качестве внешнего ключа

Шон МакКриди
источник
9

короткий, но приятный отзыв, если он работает на вас.

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
источник
Сработал шарм, когда я пишу с PG 12.2
Джек Кинселла
5

Ни один из существующих ответов не дал мне результатов в том виде, в котором я на самом деле хотел их получить. Итак, вот мой (гигантский) запрос для поиска информации о внешних ключах.

Несколько заметок:

  • Выражения, используемые для генерации from_colsи to_colsмогут быть значительно упрощены в Postgres 9.4 и более поздних версиях.WITH ORDINALITY вместо оконного функции, используя повозка , запряженная волами я использую.
  • Те же самые выражения полагаются на планировщик запросов, не изменяющий возвращенный порядок результатов из UNNEST . Я не думаю, что это произойдет, но у меня нет внешних ключей из нескольких столбцов в моем наборе данных для тестирования. Добавление 9.4 тонкостей полностью исключает эту возможность.
  • Сам запрос требует Postgres 9.0 или более поздней версии (8.x не допускается ORDER BYв агрегатных функциях)
  • Замените STRING_AGGна, ARRAY_AGGесли вы хотите массив столбцов, а не разделенную запятыми строку.

-

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
источник
5

Еще один способ:

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
;
Конрад Перзына
источник
4

Используйте имя Первичного Ключа, на которое ссылаются Ключи, и запросите информационную схему:

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')

Здесь TABLE_NAME_pkey - это имя первичного ключа, на который ссылаются внешние ключи.

markmnl
источник
4

Вот решение от Andreas Joseph Krogh из списка рассылки PostgreSQL: http://www.postgresql.org/message-id/200811072134.44750.andreak@officenet.no

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;

Это решение обрабатывает внешние ключи, которые ссылаются на несколько столбцов, и избегает дубликатов (что некоторые другие ответы не могут сделать). Единственное, что я изменил, это имена переменных.

Вот пример, который возвращает все employeeстолбцы, которые ссылаются на permissionтаблицу:

SELECT source_column
FROM foreign_keys
WHERE source_table = 'employee'::regclass AND target_table = 'permission'::regclass;
Гили
источник
4

Чтобы расширить превосходный ответ Мартина, вот запрос, который позволяет вам фильтровать на основе родительской таблицы и отображать имя дочерней таблицы с каждой родительской таблицей, чтобы вы могли видеть все зависимые таблицы / столбцы на основе ограничений внешнего ключа в родительская таблица.

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
источник
1
Запрос в принятом ответе добавляет 1,2 секунды к запросу ~ 0,03, ваш добавляет только 0,01, спасибо!
AVProgrammer
3

Правильное решение проблемы, используя information_schemaработу с несколькими столбцами ключей, правильное объединение столбцов с разными именами в обеих таблицах, а также совместимость с 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

Примечание. Существуют некоторые различия между реализациями potgresql и sqlserver, из-за information_schemaкоторых верхний ответ дает разные результаты в двух системах - одна показывает имена столбцов для таблицы внешнего ключа, другая - для таблицы первичного ключа. По этой причине я решил вместо этого использовать вид KEY_COLUMN_USAGE.

jakubiszon
источник
Информационная схема кажется правильным ответом, но на самом деле вам нужны таблицы pg_catalog: pg_constraint и т. Д. Мы сильно пострадали от этого. если ваша база данных имеет большое количество ограничений, могут возникнуть проблемы с производительностью ...
hajikelist
Приведенное выше условие ORDINAL_POSITIONможет привести к неверному результату, если порядок столбцов во внешнем ключе отличается от порядка столбцов в уникальном ограничении. Я полагаю, что вы должны были присоединиться к kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Update : Кроме того, внешний ключ может зависеть и от УНИКАЛЬНОГО ограничения, поэтому я думаю, что вы должны удалить pks.CONSTRAINT_TYPEусловие и просто присоединиться rcк нему kcu_primaryнапрямую
easd
Я сделал аналогичный ответ здесь: 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
Пугазендхи Асаймуту
источник
2

Я написал решение, которое нравится и часто используется. Код находится по адресу http://code.google.com/p/pgutils/ . Смотрите представление pgutils.foreign_keys.

К сожалению, вывод слишком многословный, чтобы включить его здесь. Однако вы можете попробовать это в общедоступной версии базы данных здесь, например так:

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

Это работает с 8.3 по крайней мере. Я ожидаю обновления в случае необходимости в ближайшие несколько месяцев.

-Reece

Reece
источник
1
Ссылка на проект устарела.
pimlottc
@pimlottc: Перемещено на bitbucket.org/reece/pgutils . Спасибо за указание на это.
Рис
1

Я создал небольшой инструмент для запроса, а затем сравнил схему базы данных: Dump PostgreSQL db schema to text

Есть информация о ФК, но в ответе оллика более подробно.

Михал Никлас
источник
0

Примечание. Не забывайте порядок столбцов при чтении столбцов ограничений!

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
источник
0

Это то, что я сейчас использую, в нем будет показана таблица и ограничения fkey [удалите таблицу, и в ней будут перечислены все таблицы в текущем каталоге]:

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
источник
0

самый быстрый, чтобы проверить прямой ответ Bash, основанный исключительно на этом ответе

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"
Йордан Георгиев
источник