Como vejo todas as chaves estrangeiras em uma tabela ou coluna?

567

No MySQL, como obtenho uma lista de todas as restrições de chave estrangeira que apontam para uma tabela específica? uma coluna em particular? É a mesma coisa que esta pergunta sobre o Oracle , mas para o MySQL.

Christian Oudard
fonte

Respostas:

764

Para uma tabela:

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

Para uma coluna:

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

Basicamente, alteramos REFERENCED_TABLE_NAME por REFERENCED_COLUMN_NAME na cláusula where.

Vinko Vrsalovic
fonte
26
isso sempre me dá um conjunto vazio, enquanto a consulta proposta por Node abaixo funciona bem
Aguda
7
@ Agute: Tem certeza de que está perguntando sobre a tabela correta? Se a consulta do Node funcionar, é provável que você esteja perguntando sobre a outra direção (ou seja, chaves FROM minha tabela, não chaves PARA minha tabela). Isso espera que você tenha escrito '<tabela>' com o nome da tabela e sem os símbolos <<e '>' ?
Vinko Vrsalovic
3
Parece que eu entendi mal a sua consulta, porque estava consultando as chaves que referenciavam FROM <table> :) (sim, eu escrevi o nome da tabela em vez de "<table>" XD)
Aguda
4
A menos que você tenha certeza de que o nome da tabela é único, provavelmente também desejará restringir sua consulta a um banco de dados específico. Altere a cláusula where para:where REFERENCED_TABLE_SCHEMA = 'mydatabase' and REFERENCED_TABLE_NAME = 'mytable'
user12345
Isso não vai funcionar em caso de usuário não raiz mesmo que o usuário tem todas as permissões para o banco de dados
Deepak Ram
275

EDIT: Como indicado nos comentários, esta não é a resposta correta para a pergunta do OP, mas é útil conhecer este comando. Essa pergunta apareceu no Google para o que eu estava procurando e achei que eu deixaria essa resposta para os outros encontrarem.

SHOW CREATE TABLE `<yourtable>`;

Encontrei esta resposta aqui: MySQL: show constraints on tables command

Eu precisava desse caminho porque queria ver como o FK funcionava, em vez de apenas ver se ele existia ou não.

CenterOrbit
fonte
37
Isso mostra todas as restrições em <yourtable>, nem todas as restrições que apontam para <yourtable>.
Barmar 21/04
18
Como o @Barmar diz, isso é totalmente errado; ele vai mostrar as chaves estrangeiras pertencentes a tabela especificada, mas não vai mostrar as chaves estrangeiras apontando PARA tabela, que é o que a questão pede. Não faço ideia de como isso conseguiu 50 votos positivos; Acho que as pessoas acabaram aqui quando realmente procuravam a resposta para a pergunta oposta, encontraram a resposta aqui de qualquer maneira e não se deram ao trabalho de ler a pergunta original (ou mesmo o título) antes de votar.
Mark Amery
2
@MarkAmery: este é o primeiro resultado de display foreign keys mysqlno google, pode ser por isso;)
Jigar
1
thisi realmente mostra todas as restrições existentes, o phpmyadmin mostrará apenas a que está apontando para a sua tabela. parece bom o suficiente para duplicatas evitar com uma ferramenta ORM
william.eyidi
3
Era isso que eu estava procurando, então obrigado por postá-lo, mesmo que não tenha respondido à pergunta da OP. Nunca é demais saber como olhar nas duas direções em um relacionamento!
Charles Wood
75

Se você usa o InnoDB e define FKs, pode consultar o banco de dados information_schema, por exemplo:

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

fonte
15
na verdade, isso aponta na direção errada. essa consulta mostra todas as chaves estrangeiras apontando para 'mytable', nem todas as chaves estrangeiras apontando para 'mytable'.
Christian Oudard 14/10/08
1
Este funciona melhor no meu caso. Eu preciso eliminar todas as restrições de chave estrangeira (e somente essas) de uma tabela para poder alterar o mecanismo InnoDB MyISAM ou NDB.
Kohányi Róbert
Você pode obter chaves estrangeiras nas duas direções na tabela REFERENTIAL_CONSTRAINTS - adicionei outra resposta à consulta.
ChrisV
45

Postagem em uma resposta antiga para adicionar algumas informações úteis.

Eu tive um problema semelhante, mas também queria ver o CONSTRAINT_TYPE junto com os nomes de tabela e coluna REFERENCED. Assim,

  1. Para ver todos os FKs na sua tabela:

    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. Para ver todas as tabelas e FKs no seu esquema:

    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. Para ver todos os FKs no seu banco de dados:

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

Lembrar!

Isso está usando o mecanismo de armazenamento InnoDB. Se você não consegue exibir nenhuma chave estrangeira depois de adicioná-la, provavelmente é porque suas tabelas estão usando o MyISAM.

Checar:

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

Para corrigir, use o seguinte:

ALTER TABLE `<yourtable>` ENGINE=InnoDB;
Andy
fonte
8
Essas consultas são executadas muito mais rapidamente (de 2 segundos a 0,0015 segundos) se você especificar k.TABLE_SCHEMA = DATABASE () e k.TABLE_NAME = '<table>' na cláusula WHERE, conforme documentado aqui dev.mysql.com/doc/refman /5.5/en/…
guigouz 21/01
2
Ótima resposta. Você tem alguma solução para o MyISAM?
Beau Bouchard
2
O MyISAM não suporta chaves estrangeiras, infelizmente. dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
Andy
24

Como alternativa à resposta do nó, se você usar o InnoDB e definir FKs, poderá consultar o banco de dados information_schema, por exemplo:

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

para chaves estrangeiras de <table> ou

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

para chaves estrangeiras em <table>

Você também pode obter o UPDATE_RULE e DELETE_RULE, se desejar.

ChrisV
fonte
2
Pessoalmente, prefiro essa resposta, pois o uso da tabela REFERENTIAL_CONSTRAINTS fornece a regra de atualização e cascata. +1
Luke Madhanga
Ao descobrir sobre uma tabela, você não deve esquecer que as chaves estrangeiras podem ser estabelecidas de duas maneiras!
Codificador
11

Esta solução não apenas exibirá todas as relações, mas também o nome da restrição, que é necessário em alguns casos (por exemplo, contra-queda):

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;

Se você deseja verificar as tabelas em um banco de dados específico, no final da consulta, adicione o nome do esquema:

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

Da mesma forma, para um nome de coluna específico, adicione

e nome_tabela = 'nome_tabela

no final da consulta.

Inspirado por este post aqui

Panayotis
fonte
7

O uso de REFERENCED_TABLE_NAME nem sempre funciona e pode ser um valor NULL. A seguinte consulta pode funcionar:

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '<table>';
Hazok
fonte
4

Uma maneira rápida de listar seus FKs (referências de chave estrangeira) usando o

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;

Esta consulta assume que as restrições e todas as tabelas referenciadas e de referência estão no mesmo esquema.

Adicione seu próprio comentário.

Fonte: manual oficial do mysql.

Daniel Rodas
fonte
3

A solução que encontrei é frágil; depende da convenção de nomenclatura do django para chaves estrangeiras.

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

Então, na concha,

grep 'refs_tablename_id' mysql_output
Christian Oudard
fonte
2

Para encontrar todas as tabelas que contêm uma chave estrangeira específica , comoemployee_id

SELECT DISTINCT TABLE_NAME 
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('employee_id')
AND TABLE_SCHEMA='table_name';
Anthony Vipond
fonte
2

Se você também deseja obter o nome da coluna da chave estrangeira:

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
fonte
Obrigado ótima solução! Eu também precisava do nome da coluna, para obtê-lo, adicione: 'k.COLUMN_NAME'
Andreas