Как просмотреть все внешние ключи для таблицы или столбца?

567

В MySQL, как я могу получить список всех ограничений внешнего ключа, указывающих на конкретную таблицу? конкретный столбец? Это то же самое, что и вопрос Oracle , но для MySQL.

Кристиан Оудард
источник

Ответы:

764

Для таблицы:

SELECT 
  TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
  INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
  REFERENCED_TABLE_SCHEMA = '<database>' AND
  REFERENCED_TABLE_NAME = '<table>';

Для столбца:

SELECT 
  TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
  INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
  REFERENCED_TABLE_SCHEMA = '<database>' AND
  REFERENCED_TABLE_NAME = '<table>' AND
  REFERENCED_COLUMN_NAME = '<column>';

По сути, мы изменили REFERENCED_TABLE_NAME на REFERENCED_COLUMN_NAME в предложении where.

Винко Врсалович
источник
26
это всегда дает мне пустой набор, в то время как запрос, предложенный узлом ниже, работает нормально
Acute
7
@ Острый: Вы уверены, что спрашиваете о правильной таблице? Если запрос узла работает, то вы, вероятно, спрашиваете о другом направлении (то есть ключах от mytable, а не ключах к mytable.) Это предполагает, что вы написали «<table>» с именем таблицы и без «<» и «>». ?
Винко Врсалович
3
Похоже , я неправильно понял вопрос, потому что я был запрашивая для ключей , ссылающихся ИЗ <table> :) (да, я написал имя таблицы вместо «<table>» XD)
Острые
4
Если вы не уверены, что имя таблицы уникально, возможно, вы захотите ограничить свой запрос определенной базой данных. Измените условие where на следующее:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345,
Это не будет работать в случае, если пользователь не является root, даже если у пользователя есть все права доступа к базе данных
Deepak Ram,
275

РЕДАКТИРОВАТЬ: Как указано в комментариях, это не правильный ответ на вопрос ОП, но полезно знать эту команду. Этот вопрос появился в Google для того, что я искал, и решил, что я оставлю этот ответ для других.

SHOW CREATE TABLE `<yourtable>`;

Я нашел этот ответ здесь: MySQL: показать ограничения на таблицы команд

Мне нужен был этот способ, потому что я хотел увидеть, как функционирует ФК, а не просто посмотреть, существует он или нет.

CenterOrbit
источник
37
Это показывает все ограничения <yourtable>, а не все ограничения, на которые указывают <yourtable>.
Бармар
18
Как говорит @Barmar, это совершенно неправильно; он будет показывать внешние ключи , относящиеся к указанной таблице, но не будет показывать внешние ключи , указывающие К столу, что и задает вопрос для. Не знаю, как это получило 50 голосов; Я полагаю, что люди оказались здесь, когда действительно искали ответ на противоположный вопрос, все равно нашли здесь свой ответ и не удосужились прочитать оригинальный вопрос (или даже его название) перед голосованием.
Марк Амери
2
@MarkAmery: это первый результат display foreign keys mysqlв Google, может быть, поэтому;)
Jigar
1
Это фактически показывает все существующие ограничения, phpmyadmin покажет вам только тот, который указывает на вашу таблицу. кажется достаточно хорошим, чтобы избежать дубликатов с помощью инструмента ORM
william.eyidi
3
Это то, что я искал, так что спасибо за публикацию, хотя он не ответил на вопрос OP. Никогда не больно знать, как смотреть в обоих направлениях в отношениях!
Чарльз Вуд
75

Если вы используете InnoDB и определили FK, вы можете запросить базу данных information_schema, например:

SELECT * FROM information_schema.TABLE_CONSTRAINTS 
WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY' 
AND information_schema.TABLE_CONSTRAINTS.TABLE_SCHEMA = 'myschema'
AND information_schema.TABLE_CONSTRAINTS.TABLE_NAME = 'mytable';
Узел
источник
15
на самом деле, это указывает на неправильное направление. этот запрос показывает все внешние ключи, указывающие на «mytable», а не все внешние ключи, указывающие на «mytable».
Кристиан Оуард
1
Этот работает лучше в моем случае. Мне нужно удалить все ограничения внешнего ключа (и только те) из таблицы, чтобы можно было изменить движок InnoDB MyISAM или NDB.
Коханьи Роберт
Вы можете получить внешние ключи в обоих направлениях из таблицы REFERENTIAL_CONSTRAINTS - я добавил еще один ответ с запросом.
ChrisV
45

Публикация старого ответа для добавления полезной информации.

У меня была похожая проблема, но я также хотел увидеть CONSTRAINT_TYPE вместе с именами таблицы и столбца REFERENCED. Так,

  1. Чтобы увидеть все ФК в вашей таблице:

    USE '<yourschema>';
    
    SELECT i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
    FROM information_schema.TABLE_CONSTRAINTS i 
    LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
    WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY' 
    AND i.TABLE_SCHEMA = DATABASE()
    AND i.TABLE_NAME = '<yourtable>';
  2. Чтобы увидеть все таблицы и FK в вашей схеме:

    USE '<yourschema>';
    
    SELECT i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
    FROM information_schema.TABLE_CONSTRAINTS i 
    LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
    WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY' 
    AND i.TABLE_SCHEMA = DATABASE();
  3. Чтобы увидеть все FK в вашей базе данных:

    SELECT i.TABLE_SCHEMA, i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
    FROM information_schema.TABLE_CONSTRAINTS i 
    LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
    WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY';

Помните!

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

Проверить:

SELECT * TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = '<yourschema>';

Чтобы исправить, используйте это:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;
Энди
источник
8
Эти запросы выполняются намного быстрее (от 2 секунд до 0,0015 секунд), если вы задаете k.TABLE_SCHEMA = DATABASE () и k.TABLE_NAME = '<table>' в предложении WHERE, как описано
Гигуз
2
отличный ответ. Есть ли у вас какие-либо решения для MyISAM?
Бо Бушар
2
MyISAM, к сожалению, не поддерживает внешние ключи. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Энди
24

В качестве альтернативы ответу Node, если вы используете InnoDB и определили FK, вы можете запросить базу данных information_schema, например:

SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = '<schema>'
AND TABLE_NAME = '<table>'

для внешних ключей из <таблицы> или

SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = '<schema>'
AND REFERENCED_TABLE_NAME = '<table>'

для внешних ключей в <table>

Вы также можете получить UPDATE_RULE и DELETE_RULE, если хотите.

ChrisV
источник
2
Я лично предпочитаю этот ответ, поскольку использование таблицы REFERENTIAL_CONSTRAINTS дает вам правило обновления и каскадирования. +1
Люк Мадханга
Делая открытие о таблице, вы не должны забывать, что внешние ключи могут быть установлены ОБОИМИ способами!
Кодировщик
11

Это решение будет отображать не только все отношения, но также и имя ограничения, которое требуется в некоторых случаях (например, ограничение на удаление):

select
    concat(table_name, '.', column_name) as 'foreign key',
    concat(referenced_table_name, '.', referenced_column_name) as 'references',
    constraint_name as 'constraint name'
from
    information_schema.key_column_usage
where
    referenced_table_name is not null;

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

select
    concat(table_name, '.', column_name) as 'foreign key',
    concat(referenced_table_name, '.', referenced_column_name) as 'references',
    constraint_name as 'constraint name'
from
    information_schema.key_column_usage
where
    referenced_table_name is not null
    and table_schema = 'database_name';

Аналогично, для конкретного имени столбца добавьте

и table_name = 'table_name

в конце запроса.

Вдохновленный этим постом здесь

Panayotis
источник
7

Использование REFERENCED_TABLE_NAME не всегда работает и может иметь значение NULL. Следующий запрос может работать вместо:

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '<table>';
Hazok
источник
4

Быстрый способ перечислить свои FK (ссылки на внешние ключи), используя

KEY_COLUMN_USAGE view:

SELECT CONCAT( table_name, '.',
column_name, ' -> ',
referenced_table_name, '.',
referenced_column_name ) AS list_of_fks
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = (your schema name here)
AND REFERENCED_TABLE_NAME is not null
ORDER BY TABLE_NAME, COLUMN_NAME;

Этот запрос предполагает, что ограничения и все ссылочные таблицы и таблицы ссылок находятся в одной и той же схеме.

Добавьте свой комментарий.

Источник: официальное руководство по MySQL.

Даниэль Родас
источник
3

Решение, которое я нашел, хрупкое; он основан на соглашении об именовании внешних ключей django.

USE information_schema;
tee mysql_output
SELECT * FROM TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_SCHEMA = 'database_name';
notee

Затем в оболочке

grep 'refs_tablename_id' mysql_output
Кристиан Оудард
источник
2

Чтобы найти все таблицы, содержащие определенный внешний ключ, такой какemployee_id

SELECT DISTINCT TABLE_NAME 
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('employee_id')
AND TABLE_SCHEMA='table_name';
Энтони Випонд
источник
2

Если вы также хотите получить имя столбца внешнего ключа:

SELECT i.TABLE_SCHEMA, i.TABLE_NAME, 
       i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, 
       k.COLUMN_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME 
  FROM information_schema.TABLE_CONSTRAINTS i 
  LEFT JOIN information_schema.KEY_COLUMN_USAGE k 
       ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME 
 WHERE i.TABLE_SCHEMA = '<TABLE_NAME>' AND i.CONSTRAINT_TYPE = 'FOREIGN KEY' 
 ORDER BY i.TABLE_NAME;
omarjebari
источник
Спасибо отличное решение! Мне также нужно было имя столбца, чтобы добавить его: 'k.COLUMN_NAME'
Andreas