SQL для отображения всех таблиц, которые ссылаются на определенный столбец в таблице - PullRequest
50 голосов
/ 18 марта 2011

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

Ответы [ 6 ]

61 голосов
/ 18 марта 2011
select R.TABLE_NAME
from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE u
inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS FK
    on U.CONSTRAINT_CATALOG = FK.UNIQUE_CONSTRAINT_CATALOG
    and U.CONSTRAINT_SCHEMA = FK.UNIQUE_CONSTRAINT_SCHEMA
    and U.CONSTRAINT_NAME = FK.UNIQUE_CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE R
    ON R.CONSTRAINT_CATALOG = FK.CONSTRAINT_CATALOG
    AND R.CONSTRAINT_SCHEMA = FK.CONSTRAINT_SCHEMA
    AND R.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
WHERE U.COLUMN_NAME = 'a'
  AND U.TABLE_CATALOG = 'b'
  AND U.TABLE_SCHEMA = 'c'
  AND U.TABLE_NAME = 'd'

При этом используется полный триплет каталога / схемы / имени для идентификации таблицы БД из всех 3 представлений information_schema.Вы можете отбросить один или два при необходимости.

В запросе перечислены все таблицы, которые имеют ограничение внешнего ключа для столбца 'a' в таблице 'd'

53 голосов
/ 15 января 2014

Не гарантируется, что другие решения будут работать в postgresql , так как не гарантируется, что имя_ограничения будет уникальным;Таким образом, вы получите ложные срабатывания.PostgreSQL называл ограничения глупыми вещами, такими как '$ 1', и если у вас есть старая база данных, которую вы поддерживали с помощью обновлений, у вас, вероятно, все еще есть некоторые из них.

Поскольку этот вопрос был нацелен на ATPostgreSQL и это то, что вы используете, затем вы можете запросить внутренние таблицы postgres pg_class и pg_attribute, чтобы получить более точный результат.

ПРИМЕЧАНИЕ: FK могут быть на нескольких столбцах, таким образом, ссылочный столбец (attnum of pg_attribute) является массивом, который является причиной использования array_agg в ответе.

Единственное, что вам нужно подключить, это TARGET_TABLE_NAME:

select 
  (select r.relname from pg_class r where r.oid = c.conrelid) as table, 
  (select array_agg(attname) from pg_attribute 
   where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as col, 
  (select r.relname from pg_class r where r.oid = c.confrelid) as ftable 
from pg_constraint c 
where c.confrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME');

Если вы хотите пойти другим путем(перечислите все вещи, на которые ссылается конкретная таблица), затем просто измените последнюю строку на:

where c.conrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME');

О, и, поскольку фактический вопрос был нацелен на конкретный столбец, вы можете указать имя столбцас этим:

select (select r.relname from pg_class r where r.oid = c.conrelid) as table, 
       (select array_agg(attname) from pg_attribute 
        where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as col, 
       (select r.relname from pg_class r where r.oid = c.confrelid) as ftable 
from pg_constraint c 
where c.confrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME') and 
      c.confkey @> (select array_agg(attnum) from pg_attribute 
                    where attname = 'TARGET_COLUMN_NAME' and attrelid = c.confrelid);
9 голосов
/ 18 марта 2011

Лично я предпочитаю делать запросы на основе указанного уникального ограничения, а не столбца.Это будет выглядеть примерно так:

SELECT rc.constraint_catalog,
       rc.constraint_schema||'.'||tc.table_name AS table_name,
       kcu.column_name,
       match_option,
       update_rule,
       delete_rule
FROM information_schema.referential_constraints AS rc 
    JOIN information_schema.table_constraints AS tc USING(constraint_catalog,constraint_schema,constraint_name)
    JOIN information_schema.key_column_usage AS kcu USING(constraint_catalog,constraint_schema,constraint_name)
WHERE unique_constraint_catalog='catalog'
    AND unique_constraint_schema='schema'
    AND unique_constraint_name='constraint name';

Вот версия, которая позволяет выполнять запросы по имени столбца:

SELECT rc.constraint_catalog,
       rc.constraint_schema||'.'||tc.table_name AS table_name,
       kcu.column_name,
       match_option,
       update_rule,
       delete_rule
FROM information_schema.referential_constraints AS rc
    JOIN information_schema.table_constraints AS tc USING(constraint_catalog,constraint_schema,constraint_name)
    JOIN information_schema.key_column_usage AS kcu USING(constraint_catalog,constraint_schema,constraint_name)
    JOIN information_schema.key_column_usage AS ccu ON(ccu.constraint_catalog=rc.unique_constraint_catalog AND ccu.constraint_schema=rc.unique_constraint_schema AND ccu.constraint_name=rc.unique_constraint_name)
WHERE ccu.table_catalog='catalog'
    AND ccu.table_schema='schema'
    AND ccu.table_name='name'
    AND ccu.column_name='column';
8 голосов
/ 05 ноября 2016

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

select confrelid::regclass, af.attname as fcol,
       conrelid::regclass, a.attname as col
from pg_attribute af, pg_attribute a,
  (select conrelid,confrelid,conkey[i] as conkey, confkey[i] as confkey
   from (select conrelid,confrelid,conkey,confkey,
                generate_series(1,array_upper(conkey,1)) as i
         from pg_constraint where contype = 'f') ss) ss2
where af.attnum = confkey and af.attrelid = confrelid and
      a.attnum = conkey and a.attrelid = conrelid 
  AND confrelid::regclass = 'my_table'::regclass AND af.attname = 'my_referenced_column';

Пример набора результатов:

confrelid |         fcol         |   conrelid    |     col
----------+----------------------+---------------+-------------
 my_table | my_referenced_column | some_relation | source_type
 my_table | my_referenced_column | some_feature  | source_type

Вся благодарность Лейну и Крогу на форуме PostgreSQL .

4 голосов
/ 30 ноября 2016
SELECT
  main_table.table_name            AS main_table_table_name,
  main_table.column_name           AS main_table_column_name,
  main_table.constraint_name       AS main_table_constraint_name,
  info_other_table.table_name      AS info_other_table_table_name,
  info_other_table.constraint_name AS info_other_table_constraint_name,
  info_other_table.column_name     AS info_other_table_column_name
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE main_table
  INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS other_table
    ON other_table.unique_constraint_name = main_table.constraint_name
  INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE info_other_table
    ON info_other_table.constraint_name = other_table.constraint_name
WHERE main_table.table_name = 'MAIN_TABLE_NAME';
3 голосов
/ 01 ноября 2016

Простой запрос на восстановление имен внешнего ключа, а также имен таблиц:

SELECT CONSTRAINT_NAME, table_name
FROM
   information_schema.table_constraints 
WHERE table_schema='public' and constraint_type='FOREIGN KEY'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...